理解反射
想要理解“反射”,就必须明白“正射”,他们最大的区别在于你是否知道其中的属性和方法,如果知道就是正射;反之,你根本就不知道你要运行的类是哪个,只知道路径,并且你想要使用这个类,就是反射。(个人理解)反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。总结:动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
所谓的"正射"
开发者自己建的类,我们知道其中的属性,和方法,由此我们可以通过new关键字来创建和适用对象,这就是“正射”。
所谓的"反射"
开发者在不知道类的内容,想要知道该类的属性和方法,这个过程就叫做“反射”。
//这段代码我们理解为正
Apple apple = new Apple(); //直接初始化,「正射」
apple.setPrice(4);
//这段代码我们理解为反
Class clz = Class.forName("com.chenshuyi.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);
上面两段代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Apple),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.chenshuyi.reflect.Apple)。
反射相关的类
类名用途Class代表类的实体,在运行的Java应用程序中表示类和接口Field代表类的成员变量(成员变量也称为类的属性)Method代表类的方法Constructor代表类的构造方法
Class类常用的方法
类相关
方法用途forName(String className)根据类名返回类的对象newInstance()创建类的实例getPackage()获得类的包fgetInterfaces()获得当前类实现的类或是接口getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
获取类成员变量相关
方法用途getDeclaredField(String name)获得某个属性对象getDeclaredFields()获得所有属性对象getField(String name)获得某个公有的属性对象getFields()获得所有公有的属性对象
获取类构造器相关
方法用途getConstructor(Class… parameterTypes)获得该类中与参数类型匹配的公有构造方法getConstructors()获得该类的所有公有构造方法getDeclaredConstructor(Class… parameterTypes)获得该类中与参数类型匹配的构造方法getDeclaredConstructors()获得该类所有构造方法
获得类中方法相关的方法
方法用途getDeclaredMethods()获得该类所有方法getDeclaredMethod(String name, Class… parameterTypes)获得该类某个方法getMethods()获得该类所有公有的方法
Field类
方法用途getDeclaredFields()获取包括私有所有字段getField(String name)获取公共字段getType()返回一个Class对象getGenericType()返回一个Type对象
Method类
方法用途invoke(Object obj, Object… args)t调用方法时getField(String name)获取公共字段getType()返回一个Class对象getGenericType()返回一个Type对象
例子
Person类
package demo;
public class Person {
private int age;
private String name;
private double price;
public Person() {
super();
}
public Person(int age, String name, double price) {
super();
this.age = age;
this.name = name;
this.price = price;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
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;
}
}
try {
Class personClass = Class.forName("demo.Person");
//初始化的时候必须要有显式的构造方法,即使是无参的
Object instance = personClass.newInstance();
Field[] declaredFields = personClass.getDeclaredFields();
for (Field item : declaredFields) {
String name = item.getName();
Class typeClass = item.getType();
Type genericType = item.getGenericType();
System.out.println(name + " 的变量类型为 " + genericType.toString() + ", typeClass为:" + typeClass.getName());
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
输出结果:要注意的是如果变量类型不是基本类型,则他的类型为 class.包名
age 的变量类型为 int, typeClass为:int
name 的变量类型为 class java.lang.String, typeClass为:java.lang.String
price 的变量类型为 double, typeClass为:double
try {
Class personClass = Class.forName("demo.Person");
Object instance = personClass.newInstance();
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method item : declaredMethods) {
String name = item.getName();
Type typeClass = item.getGenericReturnType();
Type[] genericType = item.getGenericParameterTypes();
if(genericType.length!=0) {
System.out.println(name + " 的返回值为 " + typeClass.toString() + ", 参数值为:" +
genericType[0].toString());
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
输出结果:
setName 的返回值为 void, 参数值为:class java.lang.String
setAge 的返回值为 void, 参数值为:int
setPrice 的返回值为 void, 参数值为:double
项目中的例子:
public void setObjectDefaultValue(Object obj){
//获取obj的所有属性
Method[] declaredMethods = obj.getClass().getDeclaredMethods();
for(Method item : declaredMethods){
String methName = item.getName();
if(methName.substring(0,3).equals("set") && item.getGenericParameterTypes()[0].getTypeName().equals("double")){
try {
item.invoke(obj,(double)Math.round((Math.random()*3000)*100)/100);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
public void setObjectProperty(Object target, Object actual , Object assess,@Nullable Map dif) {
Field[] targetfiled = target.getClass().getDeclaredFields();
Field[] actualfiled = actual.getClass().getDeclaredFields();
Field[] assessfiled = assess.getClass().getDeclaredFields();
for(int i =0 ;i
String propertName = item.getName();
StringBuffer getbf = new StringBuffer();
getbf.append("get");
getbf.append(propertName.substring(0,1).toUpperCase());
getbf.append(propertName.substring(1));
StringBuffer setbf = new StringBuffer();
setbf.append("set");
setbf.append(propertName.substring(0,1).toUpperCase());
setbf.append(propertName.substring(1));
try {
Method getMethodtarget = target.getClass().getMethod(getbf.toString());
Method getMethodactual = actual.getClass().getMethod(getbf.toString());
Method setMethodassess = assess.getClass().getMethod(setbf.toString(),item.getType());
double difference = (double)getMethodactual.invoke(actual) - (double)getMethodtarget.invoke(target);
if(dif!=null){
if(difference>0){
dif.put(propertName,"合理");
}else {
dif.put(propertName,"不合理");
}
}
setMethodassess.invoke(assess,Math.round(difference*100)/100);
} catch (NoSuchMethodException e) {
log.error("没有找到相关get/set方法!");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
在这里插入代码片
|