zoukankan      html  css  js  c++  java
  • Java程序员面试,自动封箱/拆箱原理与包装类的缓冲机制你知道么?(转)

    概述

    本文中小编为大家细致的讲解了Java中基本数据类型对应的包装类以及包装类的缓冲机制在实际开发中的应用 。 并且对Java中基本数据类型的包装类的主要应用---自动封箱、自动拆箱做了底层剖析 。

    自JDK1.5开始, 引入了自动装箱/拆箱这一语法糖, 它使程序员的代码变得更加简洁, 不再需要进行显式转换。基本类型与包装类型在某些操作符的作用下, 包装类型调用valueOf()方法将原始类型值转换成对应的包装类对象的过程, 称之为自动装箱; 反之调用xxxValue()方法将包装类对象转换成原始类型值的过程, 则称之为自动拆箱。

    一、Java中基本数据类型各自对应的包装类

    详细的数据类型学习请参阅:数据类型总结

    二、Jav中包装类的实际应用

    封箱 :

    Integer in = new Integer(123); //将一个基本数据类型的值转换为对应的引用类型的对象。

    System.out.println(in);//打印出的是对象的值,而不是地址 --- 底层对toString做过重写
    注意:

    字符串转Integer :

    Integer in = new Integer("0x23"); //运行报错:字符串底层是以字符串数组形式存储,在转换时会一次判断每一位是不是数字,所以只支持十进制的数。
    数值型的基本数据类型的包装类都是Number类的子类。

    字符串转Boolean:

    Boolean b = new Boolean(str); //要求参数是字符串,当str="true"时 b值为 true;当str为"false"或任意字符串时,b值为false。
     

    自动封箱:

    将一个基本数据类型的变量直接赋值给对应引用类型。是JDK1.5的新特性 之一。

    底层实现:自动封箱实际上是调用了静态方法valueOf() --> Integer in = Integer.valueOf(i); valueOf返回一个Integer类型的实例。或者是类似于上面的自动调用Integer的构造方法实现自动封箱,Integer in = 1。

    /*
    * 自动封箱的测试
    */
    int i = 1;
    int j = 1;
    Integer in1 = i;//自动封箱
    Integer in2 = Integer.valueOf(i);
    System.out.println(in1==in2);//true
    System.out.println(in1.equals(in2));//true
    System.out.println(in1.equals(j));//true
    //j是一个基本数据类型,在用equals方法进行对象的比较时,j被自动封箱
     

    自动拆箱:

    int num1 = 1;
    int num2 = 2;
    Integer in = num1;
    int res = in+num2;//拆箱
    System.out.println(res);
    //将一个引用类型的实例直接赋值给对应基本数据类型的变量。 JDK1.5的新特性之一。底层实现:实际上是调用了****value()方法(xxx指的是对应 的基本数据类型)。---> int i = in.intVlaue(); // ***value() 返回对应基本类型的值。
    整数的哈希码是自己本身。Integer底层对hashCode()方法做过重写。

    数值类型的哈希码是不变的。

    注意:

    Integer i1 = 123;

    Integer i2 = 123;

    i1==i2 ;//true;

    Integer i3 = 1234;

    Integer i4 = 1234;

    i3==i4;//false
    解释:int类型的值在常量池中初始化,只初始化-128~127的范围。所以当值在-128~127中时,是直接从从常量池中取值,而常量池中的常量是被共享的,所以i1==i2;当值 不在-128~127之间时,会new Integer(),所以i3、i4指向的堆内存地址 不一样。

    自动拆箱应用:

    Integer i1 = new Ingeter(123);

    int i = 123;

    i1 == i; //true
    解释: 当引用类型与基本类型直接运算时,引用类型会自动拆箱。

    底层的原理:自动调用了intValue()来实现拆箱。其他类型类推。

    三、包装类的缓冲机制

    包装类同String类相似,也是非可变类,其对象一经创建,就不能修改。并且,包装类也重写了equals方法,对于相同类型的两个包装类对象,只要两个对象所包装的基本数据类型的值是相等的,则equals方法就会返回true,否则返回false。
    在使用“==”比较两个包装类引用时,如果两个引用指向的地址相同(指向相同的对象),则结果为true,否则结果为false。 
    包装类提供了对象的缓存,具体的实现方式为在类中预先创建频繁使用的包装类对象,当需要使用某个包装类的对象时,如果该对象封装的值在缓存的范围内,就返回缓存的对象,否则创建新的对象并返回。 
    在包装类中,缓存的基本数据类型值得范围如下:

    包装类型 基本数据类型 缓存对象(基本数据类型值)
    Boolean boolean true,false(全部值)
    Byte byte -128~127(全部值)
    Short short -128~127
    Character char 0~127
    Integer int -128~127(默认为127)
    Long long -128~127
    Float float 无缓存值
    Double double 无缓存值
    在jdk1.5及之后的版本中,Java在5大包装类中(Byte,Charactor,Short,Integer,Long)增加了相应的私有静态成员内部类为相应包装类对象提供缓存机制,Integer包装类的内部缓存类源码如下:

    正如源码中所指,在自动装箱的基础上,缓存机制才会发生作用;当包装类加载时,内部类会初始化一个长度为((high-low)+1)的包装类类型数组,low有固定值为-128,而high的默认值为127,还可以通过系统配置文件进行修改,自定义high的取值范围是127---------(Interger.MAX_VALUE+127),Integer.MAX_VALUE是int类型变量的最大正数取值;’

    其缓存机制是:当通过自动装箱机制创建包装类对象时,首先会判断数值是否在-128----127的范围内,如果满足条件,则会从缓存中寻找指定数值,若找到缓存,则不会新建对象,只是指向指定数值对应的包装类对象,否则,新建对象。

    Integer a = new Integer(100);
    Integer b = new Integer(100);
    System.out.println(a == b);
    // 输出为false,非自动装箱机制实现,属于两个不同的对象,所以返回false.
    //--------------------------------分割线---------------------------------------
    int num1 = 127;
    int num2 = 127;//
    Integer in1 = num1;
    Integer in2 = num2;
    System.out.println(in1 == in2);//true
    //全部都在范围之内,所以为true
    //--------------------------------分割线---------------------------------------
    int num3 = 127;
    int num4 = 128;//超过了上限,成为一个缓冲范围外的新对象
    Integer in3 = num3;
    Integer in4 = num4;
    System.out.println(in3 == in4);//false
    //num4的包装类in4超过了上限,成为一个缓冲范围外的新对象,所以为false
     

    其实,Integer的缓存下限固定为-128,而缓存上限是可以在运行时通过修改系统属性来设置的。 
    比如可以在命令行输入:

    java -Djava.lang.Integer.IntegerCache.high=100 xxx
       或者在选择server虚拟机时,输入:

    java -server -XX:AutoBoxCacheMax=100 xxx
           如果去掉-server参数,将报错,这是因为,默认的虚拟机是client虚拟机,也就是不加参数或者使用-client参数时系统选择的虚拟机,而client虚拟机不支持-XX:AutoBoxCacheMax参数。 
           如果同时使用以上方式来设置缓存上限属性,以-XX:AutoBoxCacheMax参数为准。

    后记
    ————————————————
    版权声明:本文为CSDN博主「hu_beliefs」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/hu_belif/article/details/82262579

  • 相关阅读:
    友元函数和友元类
    分别用C和C++来实现一个链栈
    static 与单例模式、auto_ptr与单例模式、const 用法小结、mutable修饰符
    四种对象生存期和作用域、static 用法总结
    static 成员变量、static 成员函数、类/对象的大小
    深拷贝与浅拷贝、空类与空数组
    初始化列表(const和引用成员)、拷贝构造函数
    构造函数、析构函数、赋值与初始化、explicit关键字
    类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
    引用、数组引用与指针引用、内联函数inline、四种类型转换运算符
  • 原文地址:https://www.cnblogs.com/ffaiss/p/11460610.html
Copyright © 2011-2022 走看看