Java笔记-反射

Java笔记-反射Reflection

【韩顺平讲Java】Java反射专题 -反射 反射机制 类加载 reflection Class 类结构 等_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

为什么需要反射?

大部分的框架都是基于Java中的反射机制实现的,可以说是反射成就了Java的繁荣。

设想有这样一个场景:通过读取配置文件,创建需要的对象,并调用配置文件中指定的方法。这样我们可以仅仅通过修改配置文件就可以改变业务功能,而不用去改变代码。在这种场景下,就正好可以通过反射来实现。这种场景就经常出现在一些框架的实现中,同时也体现了设计模式中的开闭原则OCP。

是什么?

image-20210504211008065

怎么使用?

image-20210504214623691

image-20210504214718992

1
2
3
4
5
6
7
8
9
10
11
12
Class cls = Class.forName("com.twg.Cat");

Method m = cls.getMethod("hi"); //获取方法
m.invoke(); // 执行方法

Object o = cls.newInstance(); // 获取对象
Field f = cls.getField("name"); // 获取属性
f.get(o);


cls.getConstructor(); // 获取构造方法
cls.getConstructor(String.class); // 获取带参数的构造方法

image-20210504214819250

image-20210504215446703

1
method.setAccessible(true);  // 取消访问检查

Class类

Class的几种成员方法

image-20210504220901447

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Class<?> cls = Class.forName("com.twg.Car");
System.out.println(cls); // com.twg.Car
System.out.println(cls.getClass()); // java.lang.Class
System.out.println(cls.getPackage().getName()); // com.twg

// 通过cls创建对象实例
Car car = (Car)cls.newInstance();

// 获取属性,但是该方法不能获取私有属性
Field brand = cls.getField("barnd");
System.out.println(brand.get(car));
brand.set(car,"奔驰");

// 获取所有属性
Field[] fields = cls.getFields();

获取类对象的几种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1) Class.forName()	已知类的全路径,一般读取配置文件获取
Class.forName("xxx.xxx");

// 2) 类名.class 用于参数传递
System.out.println(Car.class);

// 3) 对象.getClass() 有对象实例时
car.getClass();

// 4) 通过类加载器【4种】
ClassLoader classLoader = car.getClass().getClassLoader();
Class cls = classLoader.loadClass(classAllPath);

// 5) 基本数据类型(int short long float double char boolean byte)
Class cls = int.class;

// 6) 基本数据类型的包装类
Class cls = Integer.TYPE;

动态加载&静态加载

静态加载:编译时就加载这个类,如果没有就会报错,依赖性太强

动态加载:运行时才加载,降低了依赖性,反射就是动态加载

类加载

image-20210505161219670

image-20210505161619906

  1. 加载

    将字节码从不同的数据源(class文件、jar包、网络)转化为二进制字节流加载到内存中,并生成该类的java.lang.Class对象。

  2. 连接

    image-20210505162004958

    image-20210505162255152

    image-20210505162709684

  3. 初始化

    image-20210505163248206

获取类的结构信息

image-20210505170602330

反射”爆破”

所谓爆破,就是可以访问到私有的属性或方法。

爆破创建实例

1
2
3
4
Constructor con = userClass.getDeclaredConstructor(int.class,String.class);
con.setAccessible(true); // 爆破
Object obj = con.newInstance(100,"Bob");

爆破操作属性

1
2
3
4
Field f = userClass.getDeclaredField("age");
f.setAccessible(true);
f.set(对象obj,100);
f.get(对象obj); //如果是静态属性,obj这个参数可以写null

爆破方法

1
2
3
Method m = userClass.getDeclaredMethod(方法名,XX.class);
m.setAccessible(true); // 爆破
Object returnValue = m.invoke(obj,实参列表); // 静态方法,obj可以填null

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!