Integer.valueOf(Integer intObj)运行过程及引发的其它问题

来源:互联网 发布:广东seo外包公司 编辑:程序博客网 时间:2024/05/22 08:02

首先看下下面的程序:

class Test

{

public static void main(String[] args)

{

System.out.println(Integer.valueOf(127)==Integer.valueOf(127));

System.out.println(Integer.valueOf(128)==Integer.valueOf(128));

}

}

 

返回结果为

 

 

为什么会出现这样的情况呢,127128又有什么区别呢?

Integer.valueOf() 会返回一个Integer对象,当被处理的字符串在-128127(包含边界)之间时,返回的对象是预先缓存的。这样看来第一行的两个Integer.valueOf()函数返回的是同一个对象,因此打印出true。而第二行的调用返回false是因为128没有被缓存,每次调用都会生成一个新的整型对象,因此两个128整型对象是不同的对象,返回false

可能有的朋友不理解什么是预先缓存好的对象,其实,Integer类有一个静态缓存,存储了256个特殊的Integer对象,每个对象分别对应`-128 127之间的一个值。如果传入的值(如:127)位于-128127之间,就会从静态缓存中返回对象,如果超出了这个范围就会创建一个新的对象。因此,上述程序的第一行代码是从静态缓存中返回对象,是同一个对象,而第二行是新建对象,因此两个对象不相等。

 

写到这里我有遇到了另一个问题。大家都知道HashSet类中不允许有重复的元素,根据上面的知识可以知道,当我们执行两次hashSet.add(Integer.valueOf(127));时,由于两次传入的对象是同一个,所以实际上只存入一个;当我们执行两个hashSet.add(Integer.valueOf(128));时,由于两次传入的对象不是同一个,那么会存入两个。结果是不是这样呢?我们来试验一下:

 

import java.util.*;

class Test

{

public static void main(String[] args)

{

HashSet hs1 = new HashSet();

HashSet hs2 = new HashSet();

HashSet hs3 = new HashSet();

hs1.add(Integer.valueOf(127));

hs1.add(Integer.valueOf(127));

Iterator i = hs1.iterator();

while(i.hasNext())

{

System.out.println(i.next());

}

hs2.add(Integer.valueOf(128));

hs2.add(Integer.valueOf(128));

Iterator j = hs2.iterator();

while(j.hasNext())

{

System.out.println(j.next());

}

String  s1 = new String("aa");

String  s2 = new String("aa");

hs3.add(s1);

hs3.add(s2);

Iterator k = hs3.iterator();

While(k.hasNext())

{

System.out.println(k.next());

}

}

}

运行结果如下:

 

 

显然三段程序都只存入了一个对象,那么这是怎么回事呢?

实际上HashSet中存储先判断对象的hash值,如果一样再调用equals方法判断是否是同一对象,具体细节如下(引用网上的)

要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。 也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。

由于IntegerString类重写了HashCode()方法,他们所创建出来的实例返回的hash是相同的,因此就看到第二段和第三段程序的结果和第一段一样,只存入一个。

【具体如何重写HashCode()方法以后再继续跟进】

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

【unboxing conversion】

0 0
原创粉丝点击