java反射之ObjectAnalyzer
1 在运行时使用反射分析对象
查看对象域的关键方法是Field类中的get方法,如果f是一个Field类型的对象,obj是某个包含f域的类的对象,f.get(obj)将放回一个对象,其值为obj域的当前值。
Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989);
Class cl = harry.getClass();
// the class object representing Employee
Field f = cl.getDeclaredField("name");
// the name field of the Employee class
Object v = f.get(harry);
// the value of the name field of the harry object ---> Harry Hacker
2 分析ObjectAnalyzer类
核心卷一的例子
package objectAnalyzer;
import java.util.ArrayList;
public class ObjectAnalyzerTest {
public static void main(String[] args) {
ArrayList<Integer> squares = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
squares.add(i * i);
}
System.out.println(new ObjectAnalyzer().toString(squares));
}
}
package objectAnalyzer;
import equals.Employee;
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 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();
System.out.println("cl " + cl + "@@@@@" + (cl.isArray()));
if (cl == String.class) return (String) obj;
if (cl.isArray()) {
System.out.println("^^^^^^^^^");
String r = cl.getComponentType() + "[]{";
System.out.println("current :" + r);
for (int i = 0; i < Array.getLength(obj); i++) {
if (i > 0) r += ",";
Object val = Array.get(obj, i);
System.out.println("#####" + cl.getComponentType() + "***" + cl.getComponentType().isPrimitive() + "&&&" + val);
if (cl.getComponentType().isPrimitive()) r += val;
else r += toString(val);
}
return r + "}";
}
System.out.println("**********");
String r = cl.getName();
do {
r += "[";
Field[] fields = cl.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
System.out.println("fields :" + fields.length);
for (Field f : fields) {
System.out.println(f.getName() + "~~~~~~~");
if (!Modifier.isStatic(f.getModifiers())) {
System.out.println("r***"+ r);
if (!r.endsWith("[")) r += ",";
r += f.getName() + "=";
System.out.println("r***"+ r);
try {
Class t = f.getType();
Object val = f.get(obj);
System.out.println("!!!!!!!!!" + t);
if (t.isPrimitive()) r += val;
else r += toString(val);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("r***"+ r);
}
}
r += "]";
cl = cl.getSuperclass();
System.out.println(r + "$$$$$$$$$" + cl);
} while (cl != null);
System.out.println("Finished: " + r);
return r;
}
}
-------------------------------------- 运行结果 ------------------------------------
cl class java.util.ArrayList@@@@@false
**********
fields :7
serialVersionUID~~~~~~~
DEFAULT_CAPACITY~~~~~~~
EMPTY_ELEMENTDATA~~~~~~~
DEFAULTCAPACITY_EMPTY_ELEMENTDATA~~~~~~~
elementData~~~~~~~
r***java.util.ArrayList[
r***java.util.ArrayList[elementData=
!!!!!!!!!class [Ljava.lang.Object;
cl class [Ljava.lang.Object;@@@@@true
^^^^^^^^^
current :class java.lang.Object[]{
#####class java.lang.Object***false&&&1
cl class java.lang.Integer@@@@@false
**********
fields :11
MIN_VALUE~~~~~~~
MAX_VALUE~~~~~~~
TYPE~~~~~~~
digits~~~~~~~
DigitTens~~~~~~~
DigitOnes~~~~~~~
sizeTable~~~~~~~
value~~~~~~~
r***java.lang.Integer[
r***java.lang.Integer[value=
!!!!!!!!!int
r***java.lang.Integer[value=1
SIZE~~~~~~~
BYTES~~~~~~~
serialVersionUID~~~~~~~
java.lang.Integer[value=1]$$$$$$$$$class java.lang.Number
fields :1
serialVersionUID~~~~~~~
java.lang.Integer[value=1][]$$$$$$$$$class java.lang.Object
fields :0
java.lang.Integer[value=1][][]$$$$$$$$$null
Finished: java.lang.Integer[value=1][][]
#####class java.lang.Object***false&&&4
cl class java.lang.Integer@@@@@false
**********
fields :11
MIN_VALUE~~~~~~~
MAX_VALUE~~~~~~~
TYPE~~~~~~~
digits~~~~~~~
DigitTens~~~~~~~
DigitOnes~~~~~~~
sizeTable~~~~~~~
value~~~~~~~
r***java.lang.Integer[
r***java.lang.Integer[value=
!!!!!!!!!int
r***java.lang.Integer[value=4
SIZE~~~~~~~
BYTES~~~~~~~
serialVersionUID~~~~~~~
java.lang.Integer[value=4]$$$$$$$$$class java.lang.Number
fields :1
serialVersionUID~~~~~~~
java.lang.Integer[value=4][]$$$$$$$$$class java.lang.Object
fields :0
java.lang.Integer[value=4][][]$$$$$$$$$null
Finished: java.lang.Integer[value=4][][]
#####class java.lang.Object***false&&&9
cl class java.lang.Integer@@@@@false
**********
fields :11
MIN_VALUE~~~~~~~
MAX_VALUE~~~~~~~
TYPE~~~~~~~
digits~~~~~~~
DigitTens~~~~~~~
DigitOnes~~~~~~~
sizeTable~~~~~~~
value~~~~~~~
r***java.lang.Integer[
r***java.lang.Integer[value=
!!!!!!!!!int
r***java.lang.Integer[value=9
SIZE~~~~~~~
BYTES~~~~~~~
serialVersionUID~~~~~~~
java.lang.Integer[value=9]$$$$$$$$$class java.lang.Number
fields :1
serialVersionUID~~~~~~~
java.lang.Integer[value=9][]$$$$$$$$$class java.lang.Object
fields :0
java.lang.Integer[value=9][][]$$$$$$$$$null
Finished: java.lang.Integer[value=9][][]
#####class java.lang.Object***false&&&16
cl class java.lang.Integer@@@@@false
**********
fields :11
MIN_VALUE~~~~~~~
MAX_VALUE~~~~~~~
TYPE~~~~~~~
digits~~~~~~~
DigitTens~~~~~~~
DigitOnes~~~~~~~
sizeTable~~~~~~~
value~~~~~~~
r***java.lang.Integer[
r***java.lang.Integer[value=
!!!!!!!!!int
r***java.lang.Integer[value=16
SIZE~~~~~~~
BYTES~~~~~~~
serialVersionUID~~~~~~~
java.lang.Integer[value=16]$$$$$$$$$class java.lang.Number
fields :1
serialVersionUID~~~~~~~
java.lang.Integer[value=16][]$$$$$$$$$class java.lang.Object
fields :0
java.lang.Integer[value=16][][]$$$$$$$$$null
Finished: java.lang.Integer[value=16][][]
#####class java.lang.Object***false&&&25
cl class java.lang.Integer@@@@@false
**********
fields :11
MIN_VALUE~~~~~~~
MAX_VALUE~~~~~~~
TYPE~~~~~~~
digits~~~~~~~
DigitTens~~~~~~~
DigitOnes~~~~~~~
sizeTable~~~~~~~
value~~~~~~~
r***java.lang.Integer[
r***java.lang.Integer[value=
!!!!!!!!!int
r***java.lang.Integer[value=25
SIZE~~~~~~~
BYTES~~~~~~~
serialVersionUID~~~~~~~
java.lang.Integer[value=25]$$$$$$$$$class java.lang.Number
fields :1
serialVersionUID~~~~~~~
java.lang.Integer[value=25][]$$$$$$$$$class java.lang.Object
fields :0
java.lang.Integer[value=25][][]$$$$$$$$$null
Finished: java.lang.Integer[value=25][][]
#####class java.lang.Object***false&&&null
#####class java.lang.Object***false&&&null
#####class java.lang.Object***false&&&null
#####class java.lang.Object***false&&&null
#####class java.lang.Object***false&&&null
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null}
size~~~~~~~
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null}
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=
!!!!!!!!!int
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5
MAX_ARRAY_SIZE~~~~~~~
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5]$$$$$$$$$class java.util.AbstractList
fields :1
modCount~~~~~~~
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=
!!!!!!!!!int
r***java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5]$$$$$$$$$class java.util.AbstractCollection
fields :1
MAX_ARRAY_SIZE~~~~~~~
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][]$$$$$$$$$class java.lang.Object
fields :0
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]$$$$$$$$$null
Finished: java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]
2.1 整体流程分析
一.标记对象
二.判断class是否是数组类
if yes:
1.获取数组组件类型
2.遍历数组元素
判断是否是基本数据类型
if yes:
添加到r后面
else:
递归toString(val)
3.return r
三.while循环 直到Object类
1.获取cl的所有域
2.解除安全管理器的控制
3.遍历所有的域
判断是否是非静态域
if yes:
1)域的变量名添加到r后面
2)获取域的类型 和 该域对应的值
3)判断类型是否是基本数据类型
if yes:
添加到r后面
else:
递归toString(val)
4.cl = cl.getSuperclass() 往上走
2.2 运行结果分析
squars的类型是ArrayList
ArrayList
非数组类型
共7个域 第5个域elementData是非静态域 其类型为Object[]
----------(1)-------------------
Object[]
数组类型
获取数组组件类型为Integer
----------(2) -------------------
Integer
非数组类型
共11个域 第8个域value是非静态域 其类型为int
遍历完Integer的所有域 变为Integer的父类Number
----------(3) -------------------
Number
非数组类型
共1个域 没有非静态域 变为Number的父类Object
----------(4) -------------------
Object
非数组类型
共0个域
----------(5) -------------------
(1) java.util.ArrayList[elementData=
(2) java.util.ArrayList[elementData=class java.lang.Object[]{
(3) java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1]
(4) java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][]
(5) java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][]
[]