黑马程序员_5_利用反射验证TreeSet集合只是一个包装

来源:互联网 发布:redhat linux 编辑:程序博客网 时间:2024/06/05 02:19
利用反射验证TreeSet集合只是一个包装

--------------------------------android培训java培训期待与您交流! -----------------------------------
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,双重包装。




···

最后献上一个草图~!

--------------------------------android培训java培训期待与您交流! -----------------------------------

0 0
原创粉丝点击