理解反射
- 想要理解“反射”,就必须明白“正射”,他们最大的区别在于你是否知道其中的属性和方法,如果知道就是正射;反之,你根本就不知道你要运行的类是哪个,只知道路径,并且你想要使用这个类,就是反射。(个人理解)
- 反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
- 总结:动态获取信息以及动态调用对象方法的功能称为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) {
e.printStackTrace();
} catch (InstantiationException e) {
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) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
输出结果:
setName 的返回值为 void, 参数值为:class java.lang.String
setAge 的返回值为 void, 参数值为:int
setPrice 的返回值为 void, 参数值为:double
项目中的例子:
public void setObjectDefaultValue(Object 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<String, String> dif) {
Field[] targetfiled = target.getClass().getDeclaredFields();
Field[] actualfiled = actual.getClass().getDeclaredFields();
Field[] assessfiled = assess.getClass().getDeclaredFields();
for(int i =0 ;i<targetfiled.length;i++){
Field item = targetfiled[i];
String typeName = item.getGenericType().toString();
if(typeName.equals("double")){
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();
}
}
}
}
在这里插入代码片