zoukankan      html  css  js  c++  java
  • 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]时使用的不是同一个常量池。

  • 相关阅读:
    文件上传---普通文件fileupload.jar和url文件httpUrlConnection
    HttpClient学习整理
    编写更少量的代码:使用apache commons工具类库
    多线程进阶
    多线程下HashMap的死循环问题
    线程本地变量ThreadLocal源码解读
    Eclipse工作常见问题总结
    Java集合---ConcurrentHashMap原理分析
    Java集合---Arrays类源码解析
    Java集合---LinkedList源码解析
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/13802404.html
Copyright © 2011-2022 走看看