一、反射介绍
在Java运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言习得反射(Reflection)机制。
一般而言,当用户使用一个类的时候,应该先知道这个类,然后实例化对象;反射是通过对象找到类。
二、获得Class对象
定义Demo类:
package com.example;
public class Demo {
private Integer id;
private String name;
// 无参构造器
public Demo() {
}
// 有参构造器
public Demo(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
获得Class对象:
//调用Class的静态方法:forname(String classPath)
Class clazz = Class.forName("com.example.Demo");
//调用运行时类的属性:.class
Class clazz = Demo.class;
//通过运行时类的对象,调用getClass()
Class clazz = new Demo().getClass();
//使用类的加载器:ClassLoader
ClassLoader classLoader = Demo.class.getClassLoader();
Class clazz = classLoader.loadClass("com.example.Demo");
三、创建实例
(1)无参构造器创建对象
//获取Class对象
Class clazz = Demo.class;
//获取无参构造器
Constructor constructor = clazz.getConstructor();
//创建实例
Object obj = constructor.newInstance();
(2)有参构造器创建对象
//获取Class对象
Class clazz = Demo.class;
//获取有参构造器
Constructor constructor = clazz.getConstructor(String.class);
//创建实例
Object obj = constructor.newInstance("张三");
四、获取成员变量
getFields:获得公有(public)的成员变量
getDeclareFields:获得某个类所有已声明(public、private、protected)的成员变量,不包括父类的成员变量
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MyMain {
public static void main(String[] args) {
Class clazz = Demo.class;
System.out.println("- - - getFields获取的成员变量 - - -");
Field[] fs = clazz.getFields();
for(Field f : fs){
System.out.println(f);
}
System.out.println("- - - getDeclaredFields获取的成员变量 - - -");
Field[] dfs = clazz.getDeclaredFields();
for(Field f : dfs){
System.out.println(f);
}
}
}
运行结果:
- - - getFields获取的成员变量 - - -
- - - getDeclaredFields获取的成员变量 - - -
private java.lang.Integer com.example.Demo.id
private java.lang.String com.example.Demo.name
五、获取方法
getMethods:获得所有公用(public)的方法,包括父类的公共方法
getDeclaredMethods:获得某个类已声明(public、private、protected)的所有方法,不包括父类
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MyMain {
public static void main(String[] args) {
Class clazz = Demo.class;
System.out.println("- - - getMethods获取的方法 - - -");
Method[] ms = clazz.getMethods();
for(Method m : ms){
System.out.println(m);
}
System.out.println("- - - getDeclaredMethods获取的方法 - - -");
Method[] dms = clazz.getDeclaredMethods();
for(Method m : dms){
System.out.println(m);
}
}
}
运行结果:
- - - getMethods获取的方法 - - -
public java.lang.String com.example.Demo.getName()
public java.lang.Integer com.example.Demo.getId()
public void com.example.Demo.setName(java.lang.String)
public void com.example.Demo.setId(java.lang.Integer)
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()
- - - getDeclaredMethods获取的方法 - - -
public java.lang.String com.example.Demo.getName()
public java.lang.Integer com.example.Demo.getId()
public void com.example.Demo.setName(java.lang.String)
public void com.example.Demo.setId(java.lang.Integer)
六、调用成员变量及方法
用invoke()调用方法
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MyMain {
public static void main(String[] args) {
Class clazz = Demo.class;
System.out.println("- - - 设置和获取成员值 - - -");
try {
Constructor constructor = clazz.getConstructor();
Object obj = constructor.newInstance();
Field nameF = clazz.getDeclaredField("name");
nameF.setAccessible(true);
// name成员赋值
nameF.set(obj,"张三");
// 得到name值
System.out.println(nameF.get(obj));
}catch (Exception ex){
ex.printStackTrace();
}
System.out.println("- - - 调用方法 - - -");
try {
Constructor constructor = clazz.getConstructor();
Object obj = constructor.newInstance();
// 设置值
Method nameS = clazz.getDeclaredMethod("setName", String.class);
nameS.invoke(obj,"李四");
// 获取值
Method nameG = clazz.getDeclaredMethod("getName");
Object t = nameG.invoke(obj);
System.out.println(t);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
运行结果:
- - - 设置和获取成员值 - - -
张三
- - - 调用方法 - - -
李四