使用反射的第一步,就是需要获取 Class 对象。获取 Class 对象有三种方法。
假设咱们在 com.haodf.android.entity 包下有个 Doctor 类。
Class clazz = Class.forName("com.haodf.android.entity.Doctor");
Class clazz = Doctor.class;
Doctor doctor = new Doctor();
Class clazz = doctor.getClass();
一般咱们实例化一个对象是通过 new 关键词来完成的。除了 new 之外,咱们还可以通过反射来构建对象。 通过反射构建对象有两种方式,一种是直接使用 Class.newInstance() 方法。
Object object = clazz.newInstance();
这种方式是使用了该类的默认的无参构造器来实例化一个对象。如果该类没有无参构造器,这个方法会抛出一个异常。 还有一种方式是获取构造器。
Constructor<T> getConstructor(Class...<?> parameterTypes)
Constructor[]<?> getConstructors()
Constructor<T> getDeclaredConstructor(Class...<?> parameterTypes)
Constructor[]<?> getDeclaredConstructors()
第一个和第三个是通过指定的参数类型,返回特定的构造器。第二个和第四个是返回所有构造器。 Declared 和 没有 Declared 的区别是,没有 Declared 返回是是 pubilc 的构造器,有 Declared 就包含了任何的构造器。
获取了 Contructor 对象后,可以使用 Contructor.newInstance() 方法来构造对象了。
T newInstance(Object... args)
比如:
Contructor doctorContructor = clazz.getConstructor();
Object doctorObj = personContructor.newInstance();// 注意:这里返回的是 Object ,不是 Doctor
属性和方法都是类的成员,一般属性也被称为成员变量,方法也被称为成员函数。这个体现在 Field 和 Method 都继承于 java.lang.reflect.Member 接口。
获取 Field 和 Method 的方式和构造器大致相似,这里不多说。
假设咱们的 Doctor 类里有个 age 成员变量,这个变量是 private 的,也就是咱们不能直接访问得到,更不能修改。但是咱们现在又期望能修改这个变量的值。
Field field = clazz.getDeclaredField("age"); // 因为 age 是 private 的,所以咱们使用 declared 的方式
field.setAccessible(true); // 同样因为 age 是 private 的,咱们需要设置它为可访问的。
field.set(doctorObj,50); // doctorObj 为咱们上面获取到的对象
这样子,咱们就修改了 doctorObj 的 age 属性。
下面是调用 Doctor 的 setAge 方法
Method method= clazz.getMethod("setAge");
method.invoke(doctorObj,50);
设计模式
在一些设计模式里,会使用反射机制,通过这样的方式来降低代码的耦合度。
修改和访问隐藏的属性和方法
这个也经常用到,比如上面提到的 Doctor 类,这个类不是咱们写的,咱们也没有权限去修改这个类,但是咱们又有修改 age 属性这个需求,那么可以使用反射这种黑科技。不过这样子确实破坏了代码的设计。
反射一开始不是很好理解,需要对其他一些相关的知识点也有所了解。
- EOF -
本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动。
转载请注明:文章转载自 Binkery 技术博客 [https://binkery.com]
本文标题: Java 反射 Reflection
本文地址: https://binkery.com/archives/498.html