目录反射是Java的特性之一 , 反射的核心是JVM在运行时才动态加载类或调用方法/访问属性, 他不需要事先知道运行对象是谁
一.反射的使用
(1) 获取类(2) 获得类相关方法(3)获取类中属性相关方法(4)获取类中方法相关方法 二. 反射的缺点
三. invoke方法
一.反射的使用 (1) 获取类我们可以使用三种方法获取对象的类
1.通过静态变量class2.通过getClass()对象的方法3.使用Class.forName(“类的全路径”)
public static void main(String[] args) throws ClassNotFoundException {
// 以下三种方式都可以获取Relect类 由于获取的类都是同一个所以他们equals都为true
Class> aClass1 = Class.forName("com.swei.Field.Reflect");
Class aClass2 = Reflect.class;
Reflect reflect= new Reflect();
Class extends Reflect> aClass3 = reflect.getClass();
}
(2) 获得类相关方法
获取声明的类
getDeclearedClasses() 方法返回一个Class对象的数组, 数组中包含该类中所有类和接口类的对象(包括私有的)
获取类名
getName() 方法获得类的完整路径名字
创建类的实例
newInstance() 创建类的实例, 当构造方法有参数时, 需要首先获取该类的有参构造方法
获取共有属性
getField(String name) 获得属性名为name的共有属性
getFields() 获得所有共有属性
获取声明属性
getDeclaringField(String name) 获取属性名为name的属性对象
getDeclaringFields() 获取所有属性对象可以是私有
获取类方法
getMethod(String name, Class> parameterTypes) 获取类的公共方法
getMethods() 获得该类的所有共有方法
获取声明方法
getDeclaredMethod(String name, Class...> parameterTypes) 获得该类某个方法
getDeclaredMethods() 获得该类所有方法可以是私有
- 性能差
java反射在解析类型时, 需要加载类路径, 导致性能降低安全限制
反射需要运行时权限, 这对于在安全管理器下运行的系统可能不可用安全问题
反射可以访问私有字段并且修改它的值 这可能是一个很严重的安全威胁高维护
反射代码难以理解和调试, 而且在编译时无法发现代码的问题, 因为类可能不可用,使其灵活性降低且难以维护。
当通过反射获取到类方法时, 可以通过invoke()方法对其进行调用
反射会影响到封装, 我们可以通过反射对类的私有属性和方法进行修改.
// 参数obj是实例对象, args为方法的所有参数 public Object invoke(Object obj, Object... args)
权限检查
下面来看一组代码 在Reflecte类中有两个私有属性
public class Reflect {
private String user_name;
private int age;
public Reflect(String user_name, int age) {
this.user_name = user_name;
this.age = age;
}
private int fun(int a, String b) {
System.out.println("Reflect.fun" + b);
return a;
}
@Override
public String toString() {
return "Relect{" +
"user_name='" + user_name + ''' +
", age=" + age +
'}';
}
}
public static void main(String[] args) throws Exception {
// 获取该类
Class> aClass = Class.forName("com.swei.Field.Reflect");
// 获取有参构造方法
Constructor> constructor = aClass.getConstructor(String.class, int.class);
// 根据有参构造方法创建对象
Reflect o = (Reflect) constructor.newInstance("zj", 22);
// 获取私有fun方法
Method method = aClass.getDeclaredMethod("fun", int.class, String.class);
// 方法的访问权限
method.isAccessible();
// fun方法的调用
Object fun = mehod.invoke(o, 21, "zj");
// 方法的输出
System.out.println(fun);
}
false
Exception in thread “main” java.lang.IllegalAccessException
上述代码会执行结果 会抛异常 因为isAccessible检查权限为false, 不能任意调用私有属性或方法
我们可以利用setAccessible(true)将访问权限设置为true
public static void main(String[] args) throws Exception {
// 获取该类
Class> aClass = Class.forName("com.swei.Field.Reflect");
// 获取有参构造方法
Constructor> constructor = aClass.getConstructor(String.class, int.class);
// 根据有参构造方法创建对象
Reflect o = (Reflect) constructor.newInstance("zj", 22);
// 获取私有fun方法
Method method = aClass.getDeclaredMethod("fun", int.class, String.class);
// 方法的访问权限
method.setAccessible(true);
// fun方法的调用
Object fun = mehod.invoke(o, 21, "zj");
// 方法的输出
System.out.println(fun);
}
执行结果如下:
Reflect.funzj
21



