记录下对Java反射的学习,以实现此toString方法为例
package com.xxx.javatest;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
public class ObjectAnalyzer {
private static final String TAG = "ObjectAnalyzer";
// 记录已经被访问过的对象,防止循环引用
private ArrayList<Object> visited = new ArrayList<>();
/**
* 可供任意类使用的toString方法
* @param obj an object
* @return 对象内的每个值转换为字符串
*/
public String toString(Object obj) {
if (null == obj) {
return null;
}
if (visited.contains(obj)) {
return "...";
}
visited.add(obj);
// getClass返回一个Class类型的实例,这个实例里面保存着这个对象运行时的类型信息
Class cl = obj.getClass();
// 如果这个对象是String类型的,则可以直接返回String
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 += ",";
}
// 通过反射获得数组内第i个元素
Object val = Array.get(obj, i);
// isPrimitive用来判断数组内元素是否是基本数据类型
if (cl.getComponentType().isPrimitive()) {
// 是基本数据类型,则直接加上去
r += val;
} else {
// 否则的话,递归调用toString
r += toString(val);
}
}
return r + "}";
}
String r = cl.getName();
// 开始遍历这个对象的所有域
do {
r += "[";
// 获得这个类的全部域
Field[] fields = cl.getDeclaredFields();
// 将所有域设为可访问
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;
}
// 测试
public static void main(String args[]) {
ArrayList<Integer> sq = new ArrayList<>();
sq.add(2);
sq.add(3);
sq.add(4);
System.out.println(new ObjectAnalyzer().toString(sq));
}
}
结果:
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=2][][],java.lang.Integer[value=3][][],java.lang.Integer[value=4][][],null,null,null,null,null,null,null},size=3][modCount=3][][]