反射机制使静态语言java变为准动态语言
Reflection 反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
反射方式 实例化对象--》getClass()方法--》得到完整的“包类”名称
类加载完之后,堆内存中产生一个class型对象。(一个类只能有一个Class对象),这个对象中包含了完整的类的结构信息。一个类被加载之后,所有类结构都会被封装到class对象中
反射相关的主要API
- java.lang.Class 代表一个类
- java.lang.reflect.Method 代表类的方法
- java.lang.reflect.Field 代表类的成员变量
- java.lang.reflect.Constructor 代表类的构造器
通过反射可以获取类的包名,全类名
- class.getName()
- class.getSimpleName()
可以获得类的属性
- .getFields() 获得的都是类中的非私有属性
- .getDeclaredFields() 获得全部的属性
- 以上加参数可以获得指定属性,比如.getFields("name")
可以获得类的方法
- .getMethods() 非私有方法
- .getDeclaredMethods() 全部方法
- 也可以获得指定方法如 class.getMethods("getName",null)
- 如果有重载方法的话后面给出指定参数 如class.getMethods("getName",String.class) int.class等
可以获得指定的构造器
- .getConstructors()
- .getDeclaredConstructors()
可以通过调用class对象的newInstance()方法
- 类必须有无参构造器
- 类的构造器的访问权限需要足够
还可以通过构造器创建对象
- 首先获取到对应的构造器。
- 用对应的构造器的newInstance创建一个对象
调用指定的方法
通过反射,调用类中的方法,通过Method类完成
- 通过getMethod(String name,Class parameterType ) 获取到一个Method对象。并设置此方法需要的参数类型。
- 使用 Object invoke(Object obj,Object args),并向方法中传递设置的obj对象的参数信息。
简单来说就是获得通过方法获得方法之后,通过invoke激活一下
直接上例子
package com.company;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Author:XK
* @Date: Created in 17:25 2021/10/25
* @Description: 测试反射调用一个方法
**/
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("com.company.User");
//构造一个对象
User user = (User) c1.newInstance();
System.out.println(user);
//通过构造器来构造一个对象
Constructor constructor = c1.getDeclaredConstructor(int.class);
User user2 = (User) constructor.newInstance(12);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getMethod("setName", String.class);
setName.invoke(user3,"kakaka");
System.out.println(user3.getName());
//通过反射操作属性
System.out.println("=======================");
User user4 =(User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//设置私有name是可接近的,关闭代码的安全检测
name.setAccessible(true);
name.set(user4,"xkkk2");
System.out.println(user4.getName());
}
}
setAccessible
Method Field Constructor 都是有这个方法的,作用是启动和禁止访问安全检查的开关。
true为反射的对象在使用时取消访问检查 false则实施访问检查
如果代码中频繁使用反射,设置为true。使得原本无法访问的私有成员也可以访问。