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),运行就正常了。