先上实例应用,然后总结反射操作Field
一、实例应用
需求说明:会员项目中一个人有很多身份比如张三是委员、分会成员、分会管理员、参会人员等等,这行身份公用一个会员信息SecondMember,在项目中对这些个委员管理员等进行操作时比较繁琐,针对这些操作做优化,其中一个方向就是对会员对象的操作统一为一个泛型方法,简化代码;
具体应用场景:后台方法中在原获取到人员信息(可能获取到时委员、分会成员、参会人员等情况)中统一追加会员的头像功能;
解决方法:创建泛型方法,统一对secondMember对象中追加头像地址
代码如下:
1.控制成代码
2.泛型方法代码
/**
* 通用泛型方法:在传入集合中的会员对象中加入会员的头像地址
*
* @param tList 集合对象,可以是委员、学组成员、医学会成员等包含会员对象的对象
* @return
*/
public <T> void setSecondMemberHeadImage(List<T> tList) {
for (T t : tList) {
// 1.获取泛型对应的实体类
Class<? extends Object> tClass = t.getClass();
// 2.获取tClass对象中secondMember字段,进行get set操作
Field fieldSecondMember = null;
try {
fieldSecondMember = tClass.getDeclaredField("secondMember");
} catch (NoSuchFieldException e) {
e.printStackTrace();
continue;
}
// 3.获取secondMember对象,查询会员对应头像的地址并加入到secondMember对象中
fieldSecondMember.setAccessible(true);
SecondMember secondMember = null;
try {
secondMember = (SecondMember) fieldSecondMember.get(t);
} catch (IllegalAccessException e) {
e.printStackTrace();
continue;
}
if (secondMember == null) {
continue;
}
String specImageMapJSON = getTitileImageSpecImageMapJSONByUserId(null, secondMember.getId());
secondMember.setSpecImageMapJSON(specImageMapJSON);
// 4.将新的secondMember赋值到t中的secondMember字段中
try {
fieldSecondMember.set(t, secondMember);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
实例总结:代码中主要使用Field 中get(Object object)、set(Object object, Object param)方法,get取出secondMember对象,set将含有头像地址的secondmember对象在赋值进原对象;
走的弯路:没有理解field中字段是引用对象情况的含义,一开始设计时,没有想过将secondMember对象整个取出来操作,尝试的是跨过获取secondMember直接获取secondmember中的头像地址的字段,然后对这个字段直接进行get set操作,测试后取出的头像地图的字段为null (null的情况在下面测试代码中有重现),这是因为没有获取secondmember对象的实例,获取secondMember对象,调用get方法即可;
二、Field 操作
1.测试代码
代码结构如下,一个cat类中有catinfo类型的属性;FieldsTest为测试类;
1. cat.java 代码
package importantPerson;
public class Cat {
private String name; // 猫名字
public int age; // 年龄
private String color; // 颜色
private CatInfo catInfo; // 详情:身高、体重等
public CatInfo getCatInfo() {
return catInfo;
}
public void setCatInfo(CatInfo catInfo) {
this.catInfo = catInfo;
}
public Cat(){
}
public Cat(String name, int age, String color, CatInfo catInfo) {
this.name = name;
this.age = age;
this.color = color;
this.catInfo = catInfo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", catInfo=" + catInfo +
'}';
}
}
2.catInfo.java 代码
package importantPerson;
public class CatInfo {
private Integer height;
private String weight;
@Override
public String toString() {
return "importantPerson.CatInfo{" +
"height=" + height +
", weight='" + weight + '\'' +
'}';
}
public CatInfo() {}
public CatInfo(Integer height, String weight) {
this.height = height;
this.weight = weight;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
}
3. FiedsTest.java 代码
import importantPerson.Cat;
import importantPerson.CatInfo;
import javax.persistence.criteria.CriteriaBuilder;
import java.lang.reflect.Field;
/**
* 测试反射操作
*/
public class FiedsTest {
public static void main(String[] args) throws Exception {
CatInfo catInfo = new CatInfo(3000,"1000");
Cat cat = new Cat("汤姆 tom",2,"yellow",catInfo);
Class<? extends Object> catClass = cat.getClass();
Field[] f = catClass.getDeclaredFields();
System.out.println("========循环遍历catClass开始===================");
for (Field field : f) {
System.out.println("Field对象="+field);
System.out.println("getType()="+field.getType());
System.out.println("getGenericType()="+field.getGenericType());
System.out.println("getName()="+field.getName());
System.out.println("getType().getName()="+field.getType().getName());
System.out.println("===========================");
}
System.out.println("========循环遍历结束===================");
System.out.println("========获取cat中name属性值开始===================");
Field nameField = catClass.getDeclaredField("name");
System.out.println("getDeclaredField('name')获取到的nameField="+nameField);
System.out.println(nameField.getName());//name
//importantPerson.Cat c = catClass.newInstance();
nameField.setAccessible(true);
System.out.println("get()获取name值"+nameField.get(cat));;//赋值成功
nameField.set(cat, "刘昭");//赋值成功
Object o = nameField.get(cat);
System.out.println("set()赋值‘刘昭’后获取get()获取name值"+o);//赋值成功
System.out.println("==============获取cat中name属性值结束============");
System.out.println("========获取cat中catInfo对象属性值开始===================");
Field catInfoField = catClass.getDeclaredField("catInfo");
catInfoField.setAccessible(true);
Class<?> catInfoClass = catInfoField.getType();
// newInstance()初始化一个对象,是弱创建一个新对象,此对象不许要系统加载过,GC垃圾回收的时候权限较低,可以轻易回收
// 对比new()是强创建一个新的对象;回收权限较高,不会轻易回收
Object catInfo2 = catInfoClass.newInstance();// 没有赋值的新对象,
System.out.println("newInstance实例后获取的catInfo="+catInfo2.toString());
System.out.println("========获取cat中catInfo对象属性值 结束===================");
System.out.println("========对cat中基本数据类型的age 操作===================");
Field ageField = catClass.getDeclaredField("age");
int age = ageField.getInt(cat);
System.out.println("取值age,getInt() = "+ age);
ageField.setInt(cat,20);
System.out.println("设置age后取值,getInt() = "+ ageField.getInt(cat));
System.out.println("========对cat中基本数据类型的age 操作 结束===================");
Field[] catInfoParamList = catInfoClass.getDeclaredFields();
for(Field field: catInfoParamList){
System.out.println(field);
System.out.println("getType="+field.getType());
System.out.println("getGenericType="+field.getGenericType());
System.out.println("getName="+field.getName());
System.out.println("getType.getName="+field.getType().getName());
System.out.println("===========================");
}
System.out.println("========循环遍历结束===================");
Object catInfoGet2 = catInfoField.get(cat);
System.out.println(catInfoGet2.toString());
Field heightField = catInfoClass.getDeclaredField("height");
heightField.setAccessible(true);
Integer height = (Integer) heightField.get(catInfo2);
System.out.println("newInstance实例后获取的height="+height);
heightField.set(catInfo2,40);
System.out.println("设置height后catInfo2.height="+heightField.get(catInfo2));
catInfoField.set(cat,catInfo2);
System.out.println("设置catInfo后cat="+cat.toString());
}
}
test 执行结果:
========循环遍历catClass开始===================
Field对象=private java.lang.String importantPerson.Cat.name
getType()=class java.lang.String
getGenericType()=class java.lang.String
getName()=name
getType().getName()=java.lang.String
===========================
Field对象=public int importantPerson.Cat.age
getType()=int
getGenericType()=int
getName()=age
getType().getName()=int
===========================
Field对象=private java.lang.String importantPerson.Cat.color
getType()=class java.lang.String
getGenericType()=class java.lang.String
getName()=color
getType().getName()=java.lang.String
===========================
Field对象=private importantPerson.CatInfo importantPerson.Cat.catInfo
getType()=class importantPerson.CatInfo
getGenericType()=class importantPerson.CatInfo
getName()=catInfo
getType().getName()=importantPerson.CatInfo
===========================
========循环遍历结束===================
========获取cat中name属性值开始===================
getDeclaredField('name')获取到的nameField=private java.lang.String importantPerson.Cat.name
name
get()获取name值汤姆 tom
set()赋值‘刘昭’后获取get()获取name值刘昭
==============获取cat中name属性值结束============
========获取cat中catInfo对象属性值开始===================
newInstance实例后获取的catInfo=importantPerson.CatInfo{height=null, weight='null'}
========获取cat中catInfo对象属性值 结束===================
========对cat中基本数据类型的age 操作===================
取值age,getInt() = 2
设置age后取值,getInt() = 20
========对cat中基本数据类型的age 操作 结束===================
private java.lang.Integer importantPerson.CatInfo.height
getType=class java.lang.Integer
getGenericType=class java.lang.Integer
getName=height
getType.getName=java.lang.Integer
===========================
private java.lang.String importantPerson.CatInfo.weight
getType=class java.lang.String
getGenericType=class java.lang.String
getName=weight
getType.getName=java.lang.String
===========================
========循环遍历结束===================
importantPerson.CatInfo{height=3000, weight='1000'}
newInstance实例后获取的height=null
设置height后catInfo2.height=20
设置height后catInfo2.height=40
设置catInfo后cat=Cat{name='刘昭', age=20, color='yellow', catInfo=importantPerson.CatInfo{height=40, weight='null'}}
总结:
一、Field对象基本属性说明:
nam ,type ,genericType等
1.以cat中name、catInfo字段为例--引用数据类型
Field对象=private java.lang.String importantPerson.Cat.name getType()=class java.lang.String getGenericType()=class java.lang.String getName()=name getType().getName()=java.lang.String
Field对象=private importantPerson.CatInfo importantPerson.Cat.catInfo
getType()=class importantPerson.CatInfo
getGenericType()=class importantPerson.CatInfo
getName()=catInfo
getType().getName()=importantPerson.CatInfo
2.cat中age字段 --基本数据类型 int 类型
Field对象=public int importantPerson.Cat.age
getType()=int
getGenericType()=int
getName()=age
getType().getName()=int
二、Field对象操作说明:
1.操作private修饰的字段即私有变量时候,需要强制访问,例:catInfoField.setAccessible(true);公有变量不受限值可直接访问;
2.获取Field使用 getDeclaredFields(param) 方法,其中param不传值的时候返回所有的字段field对象即Field数组,param传值的时候返回对应的字段的feild;
3.获取Field对象后,对其 操作要根据字段的类型分两类方法:
3.1基本数据类型的用一类方法:getInt(**) setInt(**),
例:int age = ageField.getInt(cat);
ageField.setInt(cat,20);
3.1引用数据类型的用一类方法:get(**) set(**);
例如:
Integer height = (Integer) heightField.get(catInfo2);
heightField.set(catInfo2,40);
注意:有资料说调用set方法,在对Intege类型字段赋值时不能自动装箱,需要new Integer();实际测试可以自动装箱;