一. Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法。Java 的这一能力在实际应用中用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。
二.
关于反射jdk对应的包是java.lang.reflect,里面有几个实现反射机制的类:
Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
三.
1.要想使用反射,首先需要获得待处理类或对象的class对象
2.获取class的三种方法。
1)通过Class.forName("");
2)通过类.class,eg:string.class;
3)通过对象的 obj.getClass();
3.若想通过类的不带参数的构造方法生成对象,有两种方式:
a)先获得class对象,然后通过class对象的newInstance()方法直接生成即可
b)先获得class对象,然后通过该对象获得对应的Constructor对象,再通过该Construtor对象的newInstance()方法生成;
Class<?> classType=StringBuffer.class;
Constructor cons=classType.geDeclaredtConstructor(new Class[]{});
Object obj=new cons.newInstance(new Object[]{});
4.
若想通过类的带参数的构造方法生成对象,只有一个方法:
先获得class对象,然后通过该对象获得对应的Constructor对象,再通过该Construtor对象的newInstance()方法生成;
Class<?> classType=StringBuffer.class;
Constructor cons=classType.getDeclaredConstructor(new Class[]{String.class,int.class});
Object obj=new cons.newInstance(new Object[]{"abing",5});
5.通过反射可以调用一个对象的private方法,或者修改一对象的private属性。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<?> classType = Class.forName("MyClass");// 把这个MyClass这个类加载进来
System.out.println("成员参数如下");
for (Field f : classType.getDeclaredFields()) {
System.out.print(f.getType() + " ");
System.out.print(f.getName() + " ");
System.out.println();
}
System.out.println("成员方法如下");
for (Method m : classType.getDeclaredMethods()) {// 打印类里的方法的信息
// 输出方法的返回类型
System.out.print(m.getReturnType().getName());
// 输出方法名
System.out.print(" " + m.getName() + "(");
// 获取方法的参数
Class<?>[] parameterTypes = m.getParameterTypes();
for (int j = 0; j < parameterTypes.length; j++) {
System.out.print(parameterTypes[j].getName());
if (parameterTypes.length > j + 1) {
System.out.print(",");
}
}
System.out.println(")");
}
Object o1 = classType.newInstance();// 通过无参的构造方法获得一个MyClass对象,最简单的方法
Constructor<?> ct = classType.getDeclaredConstructor(new Class[] {});// 获得无参的构造器
Object o2 = ct.newInstance(new Object[] {});// 用无参的构造器示例一个对象
Object o3 = classType.getDeclaredConstructor().newInstance();// 简写
Object o4 = classType.getDeclaredConstructor(// 拥有参的构造器示例一个对象
new Class[] { int.class, int.class }).newInstance(
new Object[] { 1, 2 });
MyClass o5 = (MyClass) o4;
Method m1 = classType.getDeclaredMethod("pubMeth", new Class[] {});// 调用public的方法
int temp1 = (Integer) m1.invoke(o1);
System.out.println(temp1);
Method m2 = classType.getDeclaredMethod("priMeth",
new Class[] { int.class });
m2.setAccessible(true);// 将私有的方法可访问性变成true
m2.invoke(o4, new Object[] { 9 });//调用私有的方法
System.out.println(o4);
Field name = classType.getDeclaredField("name");
name.setAccessible(true);
name.set(o4, "world");
System.out.println(o4);
}
}
class MyClass {
public int a = 1;
private int b = 2;
private String name = "hello";
MyClass() {
System.out.println("调用了无参的构造函数");
}
MyClass(int a, int b) {
this.a = a;
this.b = b;
System.out.println("调用有参的构造函数");
}
public String toString() {
return "my name is " + name + "; my value is a:" + a + " b:" + b;
}
public int pubMeth() {
return a = a + a;
}
private void priMeth(int i) {
this.b = i;
}
}