一、反射的核心思想:
将一个类中的各个成员映射成相应的java类型。如下图所示:
(所谓的成员包括:包、构造器、属性、普通方法等)
二、通过反射创建对象
<创建对象时一定会调用构造方法,因此先通过反射获取字节码(根基)
然后通过字节码来获取指定的构造方法,再通过构造器创建对象>
private static void test4() throws Exception {
//获取Class对象
Class personClass = Class.forName("zh.java.reflect1.Person");
//1.用Class对象直接调用newInstance()创建对象
Person person1 = Person.class.newInstance();
System.out.println("用Class对象直接创建的对象:"+person1);
//2.调用构造器创建对象
//①获得无参的构造方法
//getConstructor()是一个可变参数的方法,可以通过指定参数类型来获取某一具体的构造方法
Constructor constructor1 = personClass.getConstructor();
//创建对象person2:
Person person2 = (Person) constructor1.newInstance();
System.out.println("无参构造方法创建的对象:"+person2);
//②通过字节码文件获取指定参数的构造方法
Constructor constructor3 = personClass.getConstructor(String.class,int.class,float.class,double.class);
//创建对象person3:
Person person3 = (Person) constructor2.newInstance("李四",20,50,168.5);
System.out.println("有参构造方法创建的对象:"+person3);
}
*注:反射创建对象的效率比传统new对象的效率低很多;
三、通过反射来获取某一实体类对象中的属性字段
/*
getDeclaredFields():获取类中的所有字段,不包括父类声明的字段
getFields():获取某个类中所有的公共(public)字段,包括父类中的字段
*/
//获取、修改私有属性值,下面代码中的name为Person的私有属性
Field field2 = personClass.getDeclaredField("name");
System.out.println("修改name之前: "+person);
field2.setAccessible(true); //setAccessible():设置属性的可访问性,可以修改私有属性的值
field2.set(person, "王二");
System.out.println("修改name之后: "+person);
//注:类似的方法还有
getDeclaredConstructor() 与 getConstructor()
getDeclaredMethod() 与 getMethod()
四、通过反射调用实体类中指定的方法,必须知道方法名。
/*
*通过反射获取实体类的所有方法,包括继承Object类的方法
**/
private static void test1() {
Class dogClass = Dog.class;
Method[] methods = dogClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
}
运行结果:
public void zh.java.reflect.method.Dog.run()
public void zh.java.reflect.method.Dog.run(long)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
/*
*通过反射调用实体类无参的普通方法
**/
private static void test2() throws Exception {
Class dogClass = Dog.class;
// 实例方法是通过对象名调用的,因此先创建一个Dog对象
Dog dog = (Dog) dogClass.newInstance();
Method runMethod = dogClass.getMethod("run"); // 获取无参的方法,
runMethod.invoke(dog); // 调用执行方法
}
/*
* 通过反射调用实体类的有参普通方法
**/
private static void test3() throws Exception {
Class dogClass = Dog.class;
Dog dog = (Dog) dogClass.getDeclaredConstructor().newInstance();
Method runMethodArgs = dogClass.getMethod("run", long.class); //参数是参数类型的字节码
runMethodArgs.invoke(dog, 10);
}
运行结果:
Dog - run and run ! //调用无参方法
Dog - run and run 10 km! //调用有参方法