反射是指:在运行期间加载、探知和使用编译期间完全未知的能力,例如动态代理
反射依赖于Class类和java.lang.reflect类库,主要类型如下:
Class、 Field、 Method、 Constructor、 Array
其中Class类有三个特点:
1.Class类也是类的一种,class则是关键字
2.Class类只有一个构造函数,只有JVM能够创建实例
3.同一个类的对象,在JVM中只有唯一一个与之对应的CLass类实例来描述(包名+类名)
.class文件存了Class的所有信息,JVM启动时通过.class文件将相关的类加载到内存中
Class:
获取Class实例:
其中Class唯一的构造函数:
private Class(){}可以看出无法使用new来获取Class实例
Class.forName() 方法
通过forName方法来获取Class实例,该方法只能获取引用类型的类类型对象// 这种方式会使用当前的类的加载器加载,并且会将 Class 类实例初始化
Class<?> clazz = Class.forName("java.lang.String");Object.getClass() 方法可能会抛出ClassNotFoundException,原因
- 类加载器在类路径中没有找到该类
- 该类已经被某个类加载器加载到 JVM 内存中,另外一个类加载器又尝试从同一个包中加载
Class clazz = "yif".getClass();class语法
只需知道类名称即可:
Class clazz = Integer.class;包装类的TYPE静态属性
对于基本类型和void都有对应的包装类,包装类中有一个静态属性TYPE,保存了该类类型,因此生成Class类实例的方法可以为:
Class clazz = Integer.TYPE;
Class clazz2 = Void.TYPE;Field:
field提供了有关类或接口的单个属性的信息,以及对它的动态访问的能力
Method:
Method 提供了有关类或接口的单个方法的信息,以及对它的动态访问的能力
Constructor:
Constructor 提供了有关类的构造方法的信息,以及对它的动态访问的能力。
Array:
在 Java 中数组也是一种类,Array 提供了动态创建数组和访问数组元素的静态方法。
- getXX(Object array, int index):传入数组对象和下标索引,获取该位置的值
- newInstance(Clazz<?> componentType, int length):传入数组类型和长度,创建数组
int x[] = new int[10];
int y[] = (int[]) Array.newInstance(int.class, 10);
System.out.println(x.length == y.length); //结果为true
反射应用场景
动态配置:读取写好的配置文件的值,然后通过反射机制将这些值设置到配置类中