黑马程序员技术交流社区

标题: 利用反射验证TreeSet集合只是一个包装 [打印本页]

作者: Tking    时间: 2014-4-5 21:42
标题: 利用反射验证TreeSet集合只是一个包装
利用反射验证TreeSet集合只是一个包装
TreeSet集合,二叉树数据结构,存储有序,不可以存放相同对象。
TreeMap集合,二叉树数据结构,key存储有序,不同存放相同key,值没有要求,只要是Object的子类或Object类都可以。
两个都是二叉树,那不成SUN公司写了两种二叉树结构的代码?还是其中有一个只是个包装而已??不多说,先验证一下~
import java.lang.reflect.Field;
import java.util.*;
import java.util.TreeSet;
public class Demo12 {
        public static void main(String[] args)throws Exception
        {
                TreeSet ts=new TreeSet();
                ts.add(1);
                ts.add(2);
        ts.add(3);
先弄个TreeSet集合出来,然后几个值进去,具有比较性才能行,1,2,3是包装类,自动包装成Integer对象,而Integer对象又实现过Comparable,所以可以存进去。
1>弄个反射,看看TreeSet的内部成员变量是哪些??
Field[] field=ts.getClass().getDeclaredFields();
for(Field i:field)
        System.out.println(i);
运行结果:
private transient java.util.NavigableMap java.util.TreeSet.m
private static final java.lang.Object java.util.TreeSet.PRESENT
private static final long java.util.TreeSet.serialVersionUID
第一个是个Map集合的子接口,
第二个是个 常量 Object类型的。
第三个不知道是个什么······· -_-#
看样子只有这个Map集合的子接口像一个容器,那就拿它来做文章。
NavigableMap是一个接口,接口是不可以实例化的,估计是用多态的形式接收这个实例化对象的,既然知道是个Map的子接口话,子接口都可以接收,难道Map就不能接收??
2>Map来接收TreeSet里面的成员NavigableMap
首先必须实施暴力。(SUN公司写的代码,肯定很谨慎,不给你访问内部的成员)
field[0].setAccessible(true);
Map map =(Map)field[0].get(ts);
//这里要强转,jvm也不知道你取出来的是什么,所以必不可少
拿到东西了,当然先打印一下再说,看看到底是什么。(好奇心害死猫呀~~~~~
System.out.println(map);
运行结果:
{1=java.lang.Object@dea6bc,
2=java.lang.Object@dea6bc,
3=java.lang.Object@dea6bc}
这不是刚刚存进去的值么?怎么作为Key存在Map里面?而且每个Key都对应了一个Object对象,貌似地址值都是相等的??眼睛看到的,不如亲自验证。
3>map集合,取出每个Key对应的value。然后比较是否是同一个。
既然不知道取出来的是什么,那就用父类引用来接收。(上帝出马了)
Object obj1=map.get(1);
Object obj2=map.get(2);
Object obj3=map.get(3);
System.out.println(obj1.equals(obj2));
System.out.println(obj1.equals(obj3));
运行结果:
true
True
结果出来了,证明了TreeSet真的只是个包装类,里面包装了一个Map集合,TreeSet存进去的value作为该Map集合的key存进了该Map集合里,而且TreeSet里的每个value都隐式的对应着同一个value
验证TreeSet里的Object是否每个key对应的value.
field[1].setAccessible(true);
        System.out.println(obj1.equals(field[1].get(ts)));
运行结果:
True
原来这个ObjectTreeSet自动存进去的,而且始终是TreeSet.PRESENT。
那么帮TreeSet完成存储功能的Map集合跟TreeMap是什么关系呢??继承?实现?还是·······
三句代码,便出真相!
System.out.println(map.getClass()==Map.class);
System.out.println(map.getClass()==NavigableMap.class);
System.out.println(map.getClass()==TreeMap.class);
在反射中,比较两个对象的字节码是最真实可靠,这样就可以断定TreeSet到底是谁的包装。
运行结果:
false
false
True
显然这个帮助TreeSet完成存储的MapTreeMap,也就是TreeSetTreeMap的包装,而TreeMap实现存储的是内部类TreeMap.Entry,双重包装。
一个草图······







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2