对于我这样一个菜鸟级别的人来说,学习反射真心有点郁闷,今天继续分享一下学习心得。
在运行时反射分析对象,可以利用反射机制,查看数据域的实际内容,查看对象域的关键方法是Field类中的get方法,例如f是一个Field类型的对象,(通过getDeclarerFields得到的对象),obj是某个包含f域的类的对象,f.get(obj),将返回一个对象,其值为obj域当前值,直接看一下代码:
public class One {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Employee harry = new Employee("Alice Adams", 75000, 1987, 12, 15);
Class cl = harry.getClass();
System.out.println(cl);
Field f = cl.getDeclaredField("name");
System.out.println(f);
Object v = f.get(harry);
//System.out.println(v);//不能访问类的成员,因为name是私有的
//需要调用Field,Method或Constructor对象的setAccessible方法
f.setAccessible(true);
其中存在一个问题,name是私有的,所以将会抛出一个异常,除非拥有访问权限,否则Java安全机制只允许查看域还不能读取他们的值。
为了达到目的,需要调用Field、Method或者Constructor对象的setAccessible方法。
下面就是让我感到更加伤心的事情,用了一个半小时,按照书上的例子打了一个:可以供任意类使用的通用toString方法,里面有许多方法不明白,通过看源码加翻译,用了一个半小时,才有所感悟,直接看代码(分为两部分):
ObjectAnalyzer:
public class ObjectAnalyzer {
private ArrayList<Object> visited = new ArrayList<>();
/**
* converts an object to a string representation than lists all fields
* 将一个对象转换为字符串表示比列出所有类的域
* @return a string with object's class name and all fields names and values
* 返回一个带有对象的类名和所有域名和值的字符串。
*/
public String toString(Object obj) {
if (obj==null) return "null";
if (visited.contains(obj) ) return "...";
//contains();方法解释:
//Returns {@code true} if this list contains the specified element.
visited.add(obj);
Class cl = obj.getClass();
if (cl