一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,“反射”指的是通过对象找到类。
简单来说:
java反射机制简单例子
代码:
实体类
package JavaCharacter;
/**
* Created by jiangyayi on 19/5/24.
*/
public class Car {
private String brand;
private String color;
private int maxSpeed;
public Car() {
System.out.println("init car!!");
}
public Car(String brand, String color, int maxSpeed) {
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
public void introduce() {
System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed);
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
测试类
package JavaCharacter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* Created by jiangyayi on 19/5/24.
*/
public class ReflexTest {
public static Car initByDefaultConst() throws Throwable{
//①通过类装载器获取Car类对象
ClassLoader loader =Thread.currentThread().getContextClassLoader();
//loadclass可以通过getclass来获取地址
Class clazz=loader.loadClass("JavaCharacter.Car");
//②获取类的默认构造器对象并通过它实例化Car
Constructor constructor=clazz.getDeclaredConstructor((Class[]) null);
Car car = (Car) constructor.newInstance();
//③通过反射方法设置属性
Method setBrand = clazz.getMethod("setBrand", String.class);
setBrand.invoke(car, "红旗CA72");
Method setColor = clazz.getMethod("setColor", String.class);
setColor.invoke(car, "黑色");
Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
setMaxSpeed.invoke(car, 200);
return car;
}
public static void main(String args[]) throws Throwable {
Car car = initByDefaultConst();
System.out.println(car.getClass()); //打印类
car.introduce();
ReflexTest test =new ReflexTest();
System.out.println(test.getClass()); //使用实例的getClass方法找到类
System.out.println("-----------cls------------"); //打印类
Class> cls=test.getClass(); //取得class对象
System.out.println(cls.getClass()); //打印类
System.out.println(cls.getName()); //使用反射机制打印名称
}
}
类Field定义:
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
Field是一个类,位于java.lang.reflect包下。在Java反射中Field类描述的是类的属性信息,功能包括:
1.获取当前对象的成员变量的类型
2.对成员变量重新设值
方法:
1、public Field[] getFields() throws SecurityException
返回一个包含某些 Field
对象的数组,这些对象反映此 Class
对象所表示的类或接口的所有可访问公共public字段。返回数组中的元素没有排序,也没有任何特定的顺序。如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组。
getDeclaredFields(): 获取类中所有的属性(public、protected、default、private),但不包括继承的属性,返回 Field 对象的一个数组
2、public Field getField(String name throws NoSuchFieldException, SecurityException
返回一个 Field
对象,它反映此 Class
对象所表示的类或接口的指定公共成员字段。 name
参数是一个 String
,用于指定所需字段的简称。
要反映的字段由下面的算法确定。设 C 为此对象所表示的类:
NoSuchFieldException
。
3、public Field[] getDeclaredFields() throws SecurityException
返回 Field
对象的一个数组,这些对象反映此 Class
对象所表示的类或接口所声明的所有字段。包括公共public、保护protected、默认(包)访问和私有private字段,但不包括继承的字段。 返回数组中的元素没有排序,也没有任何特定的顺序。如果该类或接口不声明任何字段,或者此Class
对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。
4、public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException
返回一个 Field
对象,该对象反映此 Class
对象所表示的类或接口的指定已声明字段。 name
参数是一个 String
,它指定所需字段的简称。注意,此方法不反映数组类的 length
字段。
方法摘要:
常见错误
1.set(Object obj, Object value) 时,新value和原value的类型不一致导致,如下:无法转换类型导致 java.lang.IllegalArgumentException(注意:反射获取或者修改一个变量的值时,编译器不会进行自动装/拆箱,所以int 和Integer需手动修改)
2.set(Object obj, Object value) 时,变量访问检查导致的 IllegalAccessException。由于 Field 继承自 AccessibleObject , 我们可以使用 AccessibleObject.setAccessible() 方法告诉安全机制,这个变量可以访问即可解决,如field.setAccessible(true)。
3、getField(String name) 或getFields() 获取非 public 的变量,编译器会报 java.lang.NoSuchFieldException 错。