一、什么是反射机制?
Java 反射机制是在 运行状态中 ,对任意一个类,都能知道这个类的所有属性和方法。对任意一个对象都能调用它的任意一个方法和属性。 这种动态获取信息 和 调用 对象的方法的功能 java语言的反射机制。
简单说,反射机制指的是程序在运行时能够获取自身的信息(动态)。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
静态编译:在编译时确定类型,绑定对象。
动态编译:在运行时确定类型,绑定对象。
二、反射的应用场景
编译时类型和运行时类型
在 Java 程序中许多对象在运行是都会出现两种类型:编译时类型和运行时类型。 编译时的类型由
声明对象时实用的类型来决定,运行时的类型由实际赋值给对象的类型决定 。如:
Person p=new Student();
其中编译时类型为 Person,运行时类型为 Student。
的编译时类型无法获取具体方法
程序在运行时还可能接收到 外部传入的对象 ,该对象的编译时类型为 Object,但是程序有需要调用该对象的运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,此时就必须使用到反射了。
JDBC,对MySQL驱动类加载
Spring中也用的了反射机制,xml配置模式。
使用反射机制通过 字符串获得 某个类的class实例
动态配置实例的属性
三、java反射API(相关类)
Class类,反射的核心,可获取对象的信息(表示某个类加载后在堆中的对象)
Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性
值。
Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或
者执行方法。
Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。
四.反射的使用步骤(获取Class 对象,调用对象方法)
- 获取想要操作的类的 Class 对象,他是反射的核心,通过 Class 对象我们可以任意调用类的方法。
- 调用 Class 类中的方法,即就是反射的使用阶段。
- 使用反射 API 来操作这些信息。
五、获取Class类对象
1、Class.forName(“类的全路径”);
2. 对象.getClass();
3. 类名.class;
4. 基本类型的包装类可以,通过调用Type属性来获取Class对象。
六、调用Class类的方法
//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//获取 Person 类的所有方法信息
Method[] method=clazz.getDeclaredMethods();
for(Method m:method){
System.out.println(m.toString());
}
//获取 Person 类的所有成员属性信息
Field[] field=clazz.getDeclaredFields();
for(Field f:field){
System.out.println(f.toString());
}
//获取 Person 类的所有构造方法信息
Constructor[] constructor=clazz.getDeclaredConstructors();
for(Constructor c:constructor){
System.out.println(c.toString());
}
七、通过Class对象创建 类对象
1.Class 对象的 newInstance()
使用 Class 对象的 newInstance()方法来创建该 Class 对象 对应类 的实例,但是这种方 法要求 :该 Class 对象对应的类有默认的空构造器。
- 调用 Constructor 对象的 newInstance()
先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance()
方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。
//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性
Person p1=(Person) c.newInstance("李四","男",20);
八、反射的优缺点
优点:
(1)能够在运行时动态获取类的实例,提高灵活性。
(2)与动态编译结合
缺点:
1)使用反射性能较低,解释执行,需要解析字节码,将内存中的对象进行解析。
解决方案:
1、通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
2、多次创建一个类的实例时,有缓存会快很多
3、ReflectASM工具类,通过字节码生成的方式加快反射速度
2)相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)