Java-整数类型常量池

使用整数的封装类型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]时使用的不是同一个常量池。

 

posted @ 2021-05-26 22:46  守林鸟  阅读(222)  评论(0编辑  收藏  举报