天天看点

java 反射实际应用总结二、Field 操作二、Field对象操作说明:

先上实例应用,然后总结反射操作Field

一、实例应用

需求说明:会员项目中一个人有很多身份比如张三是委员、分会成员、分会管理员、参会人员等等,这行身份公用一个会员信息SecondMember,在项目中对这些个委员管理员等进行操作时比较繁琐,针对这些操作做优化,其中一个方向就是对会员对象的操作统一为一个泛型方法,简化代码;

具体应用场景:后台方法中在原获取到人员信息(可能获取到时委员、分会成员、参会人员等情况)中统一追加会员的头像功能;

解决方法:创建泛型方法,统一对secondMember对象中追加头像地址

代码如下:

1.控制成代码

java 反射实际应用总结二、Field 操作二、Field对象操作说明:

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为测试类;

java 反射实际应用总结二、Field 操作二、Field对象操作说明:

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();实际测试可以自动装箱;