利用反射验证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 原来这个Object是TreeSet自动存进去的,而且始终是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完成存储的Map是TreeMap,也就是TreeSet是TreeMap的包装,而TreeMap实现存储的是内部类TreeMap.Entry,双重包装。 一个草图······
|