在运行时使用反射分析对象

在运行时使用反射分析对象

看java核心技术的里面的反射的时候反射运行机制看得有些糊涂这里把代码贴上来把过程分析一遍。

  • 源码
  • 代码分析过程

源码

ObjectAnalyzer类

package zhaoch93.corejava;

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<>();

    /**
     * Converts an object to a string representation that lists all fields.
     * @param obj an object
     * @return a string with the object's class name and all field names and values
     */
    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())
        {
            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();
        //inspect the fields of this class and all superclasses
        do
        {
            r += "[";
            Field[] fields = cl.getDeclaredFields();
            AccessibleObject.setAccessible(fields, true);
            //get the names and values of all fields
            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;
    }
}

ObjectAnalyzertest类(用来测试结果)

package zhaoch93.corejava;

import java.util.ArrayList;

/**
 * This program uses reflection to spy on objects.
 * @version 2016-2-15
 * @author zhaoch93
 *
 */

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);

//      int [] [] squares2 = new int [5] [5];
//      for(int i = 0;i<5;i++)
//          for(int j = 0;j<5;j++)
//              squares2 [i] [j] = i+j;
        System.out.println(new ObjectAnalyzer().toString(squares));
//      System.out.println(new ObjectAnalyzer().toString(squares2));
    }
}

源码

把运行结果简单排版如下:

java.util.ArrayList
[
{
java.lang.Integer[value=1][][],
java.lang.Integer[value=4][][],
java.lang.Integer[value=9][][],
java.lang.Integer[value=16][][],
null,null,null,null,null,null
},
size=4
]
[modCount=4]
[]
[]

这里说明一下运行的原理。这个程序会把把运行时的非静态域都打印出来,并且将其继承的超类的域都打印出来。
首先进入程序的是一个ArrayList类。这个类自身有六个域,以及一个从java.util.AbstractList继承的类modCount分别为

private static final long java.util.ArrayList.serialVersionUID
private static final int java.util.ArrayList.DEFAULT_CAPACITY
private static final java.lang.Object[] java.util.ArrayList.EMPTY_ELEMENTDATA
private transient java.lang.Object[] java.util.ArrayList.elementData
private int java.util.ArrayList.size
private static final int java.util.ArrayList.MAX_ARRAY_SIZE
Fields inherited from class java.util.AbstractList modCount

这其中非静态类只有第四个和第五个当进入这个两个静态类的时候会嵌套调用toString。
而modCount会在cl上提为AbstractList类的适合进行toString。

整个答案的结构为:
ArrayList[….][modCount][][]
这四个方括号运行时此对象分别从ArrayList,AbstractList,AbstractCollection,Object继承的非静态域。这个顺序正好符合ArrayList的继承关系。
同理在java.lang.Integer[value=1][][]中,
之所以有三个括号也是因为,Integer,Number,Object类中继承的非静态域,只不过,Number和Object中并没有非静态域。所以为空。

现在回头看ArrayList的 elementData数据。当数据有值时进入isarray程序块。分别会对数组中每个元素进入以此toString,当然如果元素是基本类型就不用调用tostring了。当然这里面还有一个size域也需要进行tostring,但原理是一样的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值