反射---检查类的结构
1.Field、Method、Constructor类
在java.lang.reflect包中有三个类Field、Method、Constructor,分别用于描述类的域、方法和构造器。这三个类都有一个getName方法,用于返回所对应的名称。
Class类中的getFields、getMethods和getConstructors方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。
Class类的getDeclareFields、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。(如果类中没有域,或者Class对象描述的是基本类型或数组类型,这些方法将返回一个长度为0的数组)
Field类有一个getType()方法,用来返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。
这三个类还有一个叫getModifiers的方法,它将返回一个整型数值,来描述public和static修饰符使用状况(Modifier.toString(field_method_cons.getModifiers)返回修饰符字符串)。还可以使用Modifier类中的isPublic、isPrivate或isFinal判断方法或构造器是否是public、private或final。
Field、Method、Constructor类中共有方法:
-
Class getDeclaringClass()
返回构造器、方法或域所属的类的Class对象 -
Class[ ] getParameterTypes()
返回一个用于描述参数类型的Class对象数组 -
Class getReturnType()
返回一个用于描述返回类型的Class对象
2.使用反射分析对象
查看对象域的关键方法是Field类中的get方法。当然,也可以调用Field类的set方法对域值进行设置。具体操作:
Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989)
//获得Class对象
Class class = harry.getClass();
//获得Field对象
Field f = class.getDeclaredField("name");
//获得访问权限
f.setAccessible(true);
//获得域的类型
Class className = f.getType();
//获得域的值
Object v = f.get(harry);
//设置新的域值,将object对象的f域设置成新值。
Field.set(Object object, Object newValue);
f.set(harry, "YinHang");
对于属于基本数据类型的域,可以使用Field中的getDouble、getInt等方法。或者直接使用get方法,反射机制将会自动地打包到对象包装器中。
3.供任意类使用的toString方法
public class ObjectAnalyzer {
private ArrayList<Object> visited = new ArrayList<>();
public String toString (Object obj) {
if (obj == null) return null;
//好像没用
if (visited.contains(obj)) return "....";
visited.add(obj);
Class cl = obj.getClass();
if (cl == String.class) return (String) obj;
if (cl.isArray()) {
//getComponentType()返回元素类型
String r = cl.getComponentType() + "[]{";
for (int i = 0; i < Array.getLength(obj); i++) {
if (i > 0) r += ",";
Object val = Array.get(obj, i);
//元素类型是否为基本数据类型
if (cl.getComponentType().isPrimitive()) r += val;
//回调自身
else r += toString(val);
}
return r + "}";
}
String r = cl.getName();
do {
r += "[";
Field[] fields = cl.getDeclaredFields();
//设置private也可访问
AccessibleObject.setAccessible(fields, true);
for (Field f : fields) {
//非静态域
if (!Modifier.isStatic(f.getModifiers())){
if (!r.endsWith("[")) r += ",";
r += f.getName() + "=";
try {
Class t = f.getType();
Object val = f.get(obj);
if (t.isPrimitive()) r += val;
//回调自身
else r += toString(val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
r += "]";
//获取父类中的继承域
cl = cl.getSuperclass();
} while (cl != null);
return r;
}
}