使用整数的封装类型Byte、Short、Integer、Long定义变量时,经常会遇到Integer i1=1;和Integer i2=new Integer(1);判断i1==i2的情况,但是对于Short s1=1;s1和i1比较如何呢?
理论上占用的字节都不一样,应该不是同一个常量池,但是还有自动转型这个东西,所以对此有了怀疑。
1.整数类型常量池
整数类型的封装类型Byte、Short、Integer、Long会将一些常用的数放进常量池,提高性能;没有用new声明变量的情况下,默认引用堆内存上的常量池,这个范围为[-128,127],同种类型的几种声明方式及其变量指向的地址如下图所示:
拆箱,任何比较中有基本数据类型例如i2,全部自动拆箱比较数值,i1至i6与i2比较都返回true;
2.利用hashCode()判断是不是同一个对象
hashCode()就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。对象在jvm上的内存位置是唯一的,但是不同对象的hashcode可能相同,它还要包括其他内容,再根据一定的算法去算出一个值,算出来的可能一样,一样的话就是哈希冲突。
我认为哈希冲突的概率极低,虽然不同的对象算出的哈希值可能相同,写几个简单的用例不可能会遇到;
相同的对象hashCode()相同,返过来,hashCode()相同的对象地址一般都相同;
(1)声明测试类class Node{int x,y;}并测试
Node node1=new Node(); Node node2=new Node(); Node node3=node1; System.out.println(node1.hashCode());//1163157884 System.out.println(node2.hashCode());//1956725890 System.out.println(node3.hashCode());//1163157884 System.out.println(node1==node2);//false System.out.println(node1==node3);//true
普通类调用hashCode()是个native方法,返回一个哈希值,显然哈希值相同就是同一个对象;
(2)测试Integer 和 Short类型
Short s1=1; Short s2=1; Integer i1=1;
//Integer i2=s2;//报错 System.out.println(s1==s2);//true //显示异常:Operator '==' cannot be applied to 'java.lang.Short', 'java.lang.Integer' //System.out.println(s1==i1); System.out.println(s1.hashCode());// 1 System.out.println(i1.hashCode());// 1
封装类型不能自动转型;
基本数据类型调用的hashCode()则是返回数值大小,这.....怎么判断是不是同一个对象?
==也不能用来判断,这......还怎么判断?
向同学请教怎么搞到s1和i1的地址,总算知道了
3.jol-core依赖包
openjdk的一个工具,可以查看到一个对象的布局。
<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency>
System.out.println(GraphLayout.parseInstance(i1).toPrintable()); System.out.println("Current address: " + VM.current().addressOf(i1)); System.out.println("------------------------------------------------------------------"); System.out.println(GraphLayout.parseInstance(s1).toPrintable()); System.out.println("Current address: " + VM.current().addressOf(s1));
终于可以盖棺定论,不同整数的封装类型数值为[-128,127]时使用的不是同一个常量池。