JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
比如类Product如下:
package p0123;
public class Product {
private String id; //编号
private String name;//名称
private double price;//价格
Product(){};//无参构造方法
Product(String id,String name,double price){//有参构造方法
super();
this.id = id;
this.name = name;
this.price = price;
}
/*get和set方法*/
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
1、// 获得这个类的Class对象
public class ReflectTest {
// 获得一个类Class对象
@Test
public void method_1() throws ClassNotFoundException{
// 方式一 类名.class 属性获得
Class class1 = Product.class;
// 方式二 不知道类名,对象.getClass 方法
Object object = new Product();
Class class2 = object.getClass();
// 方式三:不知道类名、也不知道对象 ,只知道类全路径描述 包名.类名
String classPath = "p0123.Product";
Class class3 = Class.forName(classPath);
System.out.println(class1);//class p0123.Product
System.out.println(class2);//class p0123.Product
System.out.println(class3);//class p0123.Product
}
}
2、创建这个类的对象,通过默认构造函数)
// 创建一个类的对象(通过默认构造函数)
@Test
public void method_2() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
// 传统
Product product = new Product();
// 反射构造对象,调用默认构造函数 构造类对象
String classPath = "p0123.Product";
Class class1 = Class.forName(classPath);
Object product2 = class1.newInstance();
}
3、创建这个类的对象,通过有参构造函数
// 创建一个类对象(通过有参构造函数)
@Test
public void method_3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
// 传统
Product product = new Product("1", "wang", 10);
// 反射构造
String classPath = "p0123.Product";
Class class1 = Class.forName(classPath);
// 如果调用有参数构造器,必须获得构造器对应Constructor对象
// 因为构造器参数列表唯一的,通过参数类型列表 获得指定构造器
Constructor constructor = class1.getConstructor(String.class,String.class,double.class);
// 构造时,传入参数个数应该和获得构造器时 参数类型个数 匹配
Object product2 = constructor.newInstance("2","zhang",20);
}
4、读写成员变量
@Test
public void method_4() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException{
// 传统
Product product = new Product();
//product.name = "li"; name是私有的不能操作
// 反射
String classPath = "p0123.Product";
Class class1 = Class.forName(classPath);
Object product2 = class1.newInstance();
// 用反射操作成员变量,获得变量对应Field对象
Field field = class1.getDeclaredField("name");// 通过变量名称获得
field.setAccessible(true);// 允许访问
// 设置product2对象的name属性
field.set(product2, "li"); //product2.name = "li";
// 读取p对象的name属性
System.out.println(field.get(product2));// 相当于p.name 结果li
}
5、执行方法
// 执行方法
@Test
public void method5_5() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
// 传统
Product product = new Product();
product.setName("tra");
String name = product.getName();
System.out.println(name);//tra
// 反射
Class class1 = Class.forName("p0123.Product");
Object product2 = class1.newInstance();
// 执行方法,需要获得方法对应Method对象
// 方法由 名称和参数列表确定
// setName : 名称setName 列表String.class
Method setName = class1.getDeclaredMethod("setName", String.class);
// 执行方法
setName.invoke(product2, "zhangsan");// product2.setName("zhangsan");
// getName : 名称 getName 参数列表 无
Method getName = class1.getDeclaredMethod("getName");
// 执行方法
String name2 = (String) getName.invoke(product2);
System.out.println(name2);//zhangsan
}