反射概念
了解反射背景
存在某些变量或形参的声明类型是Object类型,但是程序却需要调用该对象运行时类型的方法,该方法不是Object中的方法,如何解决。转到如何获取该对象运行时类型的方法。
只能运行时才能获取,这就用到反射。
反射概述
Reflection被视为动态语言的关键。允许程序在运行期间借助Reflection API 取得任何类的内部信息,并能直接操作任何对象的内部属性和方法。
例如下面的案例,获取类的属性和方法,两种都是可行的。
@Test
public void test() {
// 创建Person类的实例
Person1 person1 = new Person1();
// 调用Person类的属性和方法
// 调用属性
person1.age = 10;
System.out.println(person1.age);
// 调用方法
person1.show();
}
/*
使用反射完成上述的操作
*/
@Test
public void test1() throws Exception {
// 调用构造器方法
Class<Person> personClass = Person.class;
Person person = personClass.newInstance();
System.out.println(person);
// 调用属性,先获取age属性
Field ageField = personClass.getField("age");
// 然后通过属性设置对象内部的属性值,之前是通过对象调用方法设置属性值
ageField.set(person, 10);
System.out.println(ageField.get(person));
// 调用方法
Method showMethod = personClass.getMethod("show");
showMethod.invoke(person);
}
反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 构造任意一个类的对象
- 判断任意一个类所具有的成员变量和方法
- 获取泛型信息
- 调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
Class类,java反射的源头
获取class实例的方式:
- 调用运行时类的静态属性class
- 调用运行时类的对象getClass()
- 调用Class的静态方法,forName(String className)
- 使用类的加载器方式
了解类的加载过程:
过程1:类的装载(loading)
将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成
过程2:链接(linking)
- 验证(Verify):确保加载的类信息符合JVM规范,例如:以cafebabe开头,没有安全方面的问题。
- 准备(Prepare):正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
- 解析(Resolve):虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
过程3:初始化(initialization)
执行类构造器()方法的过程。
类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。