Java 反射:Field (成员变量)

CompanyA.java
package com.mkyong.test;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class CompanyA {

    String orgName;
    int count;
    List<String> comments;
    Set<String> branches;
    Map<String, String> extra;

    //...
}

1.2 Use Java reflection APIs getDeclaredFields() to loop over and display the field name and data type.

Test.java
package com.mkyong.test;

import java.lang.reflect.Field;
import java.util.List;

public class Test {

    public static void main(String[] args) {

        Field[] fields = CompanyA.class.getDeclaredFields();
        for(Field f : fields){
            Class t = f.getType();
            System.out.println("field name : " + f.getName() + " , type : " + t);
        }

    }

}
Copy
Output

field name : orgName , type :class java.lang.String
field name : count , type :int
field name : comments , type :interface java.util.List
field name : branches , type :interface java.util.Set
field name : extra , type :interface java.util.Map

2. Find class fields with specified data type
2.1 This example will find all fields with List data type.

Test.java
package com.mkyong.test;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class TestAbc {

    public static void main(String[] args) {

        List<String> list = getFieldNameWithListDataType();
        for(String data : list){
            System.out.println("List : " + data);
        }


    }

    private static List<String> getFieldNameWithListDataType(){

        List<String> result = new ArrayList<>();

        //CompanyA, refer 1.1
        Field[] fields = CompanyA.class.getDeclaredFields();
        for(Field f : fields){

            // use equals to compare the data type.
            if(f.getType().equals(List.class)){
                result.add(f.getName());
            }

            //for other data type
			
            //Map
            //if(f.getType().equals(Map.class)) 
			
            //Set
            //if(f.getType().equals(Set.class))
			
            //primitive int
            //if(f.getType().equals(int.class))
            //if(f.getType().equals(Integer.TYPE))
			
            //primitive long
            //if(f.getType().equals(long.class))
            //if(f.getType().equals(Long.TYPE))
			
        }

        return result;

    }

}


设置值:
People shixin = new People();
        String fmt = "%6s:  %s  = %s \n";
        Class<? extends People> cls = shixin.getClass();
        try {
            Field idCarNumber = cls.getDeclaredField("idCarNumber");
            System.out.format(fmt, "before", idCarNumber.getName(), shixin.idCarNumber);
            idCarNumber.setLong(shixin, 123456);
            System.out.format(fmt, "after", idCarNumber.getName(), shixin.idCarNumber);

            Field name = cls.getDeclaredField("name");
            System.out.format(fmt, "before", name.getName(), Arrays.asList(shixin.name));
            name.set(shixin, new String[]{"hei", "hei"});
            System.out.format(fmt, "after", name.getName(), Arrays.asList(shixin.name));

            Field habit = cls.getDeclaredField("habit");
            System.out.format(fmt, "before", habit.getName(), shixin.habit);
            habit.set(shixin, MyHabit.LOL);
            System.out.format(fmt, "after", habit.getName(), shixin.habit);


        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }


常见错误 1 :无法转换类型导致的 java.lang.IllegalArgumentException
为什么我们无法给 Integer 类型的 value 使用 setInt() 方法重新设值呢?

这是因为在使用反射获取或者修改一个变量的值时,编译器不会进行自动装/拆箱。

因此我们无法给一个 Integer 类型的变量赋整型值,必须给它赋一个 Integer 对象才可以。

使用 Field.set(Object obj, Object value) 方法解决这个问题:

f.set(ft, new Integer(43));


常见错误 2:反射非 public 的变量导致的 NoSuchFieldException
如果你使用 Class.getField() 或者 Class.getFields() 获取非 public 的变量,编译器会报 java.lang.NoSuchFieldException 错。


常见错误 3 :修改 final类型的变量导致的 IllegalAccessException
当你想要获取或者修改 不可修改(final)的变量时,会导致IllegalAccessException

这是因为在类初始化后,无形之中会有一个访问限制阻止我们修改 final 类型的变量。

由于 Field 继承自 AccessibleObject , 我们可以使用 AccessibleObject.setAccessible() 方法告诉安全机制,这个变量可以访问。

因此上面的例子中,声明这个变量是可访问的:wannaPlayGame.setAccessible(true),运行就正常了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值