首页 > 编程语言 >Java基础:自动装箱和自动拆箱

Java基础:自动装箱和自动拆箱

时间:2023-06-23 09:11:13浏览次数:50  
标签:拆箱 Java System 自动 println Integer 装箱 out

感谢,原文链接:
https://www.cnblogs.com/dolphin0520/p/3780005.html

Java的自动包装类型

首先基本数据类型:4类8种

基本数据类型 对应包装器类
byte(1字节) Byte
short(2字节) Short
int(4字节) Integer
long(8字节) Long
float(4字节) Float
double(8字节) Double
char(2字节) Character
boolean(未定) Boolean

自动装箱就是自动将基本数据类型转换为包装器类型;
自动拆箱就是自动将包装器类型转换为基本数据类型。
简单来说就是:
Integer i = 1; //装箱
int j = i; //拆箱

装箱和拆箱怎么实现的

public static void main(String[] args) {

        Integer i = 1;
        int j = i;

}
123456

上面的代码反编译后如下图
在这里插入图片描述
  从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。其他的也类似,比如Double、Character。
 
总结:装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。

面试题解析

public static void main(String[] args) {

        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;

        System.out.println(i1 == i2);  // true
        System.out.println(i3 == i4);  // false

    }
1234567891011

看下Integer的部分源码就知道了

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
12345
   private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

12345678910111213141516171819202122232425262728293031323334

从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

 private static void testDouble() {

        Double i1 = 100.0;
        Double i2 = 100.0;
        Double i3 = 200.0;
        Double i4 = 200.0;

        System.out.println(i1==i2); //false
        System.out.println(i3==i4); //false

}
1234567891011

在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
  注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
     Double、Float的valueOf方法的实现是类似的。

谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别

当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

    private static void testAll() {


        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Long h = 2L;

        System.out.println(c==d);  //true
        System.out.println(e==f);  //false
        System.out.println(c==(a+b));  // true
        System.out.println(c.equals(a+b)); //true
        System.out.println(g==(a+b)); // true
        System.out.println(g.equals(a+b)); //false
        System.out.println(g.equals(a+h));// true

    }
123456789101112131415161718192021

首先第一个没有什么疑问,c和d都来自缓存,所以相等输出true.

第二个e,f的输出也没什么疑问,都会创建新的对象,所以不等,输出false.

第三个可能刚刚看的时候有点懵逼,但是仔细想想就知道答案,首先会执行的是a+b,首先a和b是包装类型,是对象,他们是不可能相加的,所以先要执行拆箱的操作将a,b拆成基本数据类型再做相加的操作,完了之后与c进行比较,c是包装类型,所以c也会自动拆箱进行比较
第四个的其实就是equals()方法和 == 的区别,equals()和 == 其实一样,判断的是两个对象是否相等,但是Integer对equals()方法进行了重写,他比较的就是值,他不会进行类型转换。所以执行a+b的时候依然会有一个拆箱的过程,但是指向equals的时候她会有一个装箱的过程。所以输出的是true.

第五个和第三个有点类似,都是转化为基本的数据类型,然后比较数值,所以他们数值是相等的,返回的是true.

第六个也是先拆箱,然后相加运算,但是请注意这个和上一个直接==不同,上面可以拆箱比较数值,而这个equals()方法里面是Object类型的数据,也就是说他要传一个引用类型的参数,所以a+b会装箱成Integerr类型的数据,但是g是Long类型。类型不同就比较不了了。
第七个,对于a+h,先自动触发拆箱,就变成了int类型和long类型相加,这个会触发类型自动提升,结果是long类型的,然后会触发装箱过程,就变成Long了。因此比较结果是true。

标签:拆箱,Java,System,自动,println,Integer,装箱,out
From: https://www.cnblogs.com/javaxubo/p/17498731.html

相关文章

  • 自动驾驶的参考书籍
    以下是一些自动驾驶方面的参考书籍:《自动驾驶技术-系统化分析与探讨》:本书介绍了自动驾驶技术的基本原理、各个模块的算法细节和对应的硬件设计,同时对未来发展方向进行了讨论。《自动驾驶车辆技术导论》:本书从自动驾驶的技术背景、研究思路、关键技术等方面全面介绍了自动驾驶技术......
  • 现实中的 JAVA (一)
    买零食描述本例子主要是通过JAVA语言来描述,平时父母带我们去买零食的场景。买零食流程图从家里出发,选择一种出行方式达到零食店然后我们就可以开始购物了,选择对应的零食随后进行买单家庭成员UML图1、Person做为顶级的抽象类2、Male作为男CLass的描述类3、Fem......
  • JAVA博客3
     一.前言第三次写Blog,相比较上一次而言自己的经验更加的丰富了,这次blog的书写相对来说要更为轻松些。内容上题目较少,只需要分析有关课程成绩统计系统,但是说容易也并不容易,每一道题都是刺头中的刺头,这一次写博客,不仅仅是以完成任务的目的,更多的,让自己重新对那些打击过自己,折磨过......
  • java中的各种锁
    java中的各种锁一、概述乐观锁CAS悲观锁synchronized自旋锁CAS可重入锁synchronized、Reentrantlock、Lock读写锁ReentrantReadWriteLock,CopyOnWriteArrayList、CopyOnWriteArraySet公平锁Reentrantlock(true)非公平锁synchronized、reentrantlock(false)共享锁......
  • Java Web自定义MVC框架详解
    最近给学生讲JavaWeb,希望他们能够在学完这部分内容后自己实现一个MVC框架。但是突然发现百度上能搜索到的靠谱的资料并不是很多,有些只是原理没有代码实现,有些有代码实现但是对于初学者来说理解起来还是比较困难,于是决定把自己讲自定义MVC框架的内容放在这里分享给大家,不仅仅是代码......
  • 字符编码和Java中的乱码问题
    ASCII码  在计算机内部,所有的信息最终都表示为一堆二进制形式的数据。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,称为一个字节(byte),从0000000到11111111。上世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系做了统一规定,称之为ASCII......
  • Java Web项目中使用Freemarker生成Word文档
    Web项目中生成Word文档的操作屡见不鲜,基于Java的解决方案也是很多的,包括使用Jacob、ApachePOI、Java2Word、iText等各种方式,其实在从Office2003开始,就可以将Office文档转换成XML文件,这样只要将需要填入的内容放上${}占位符,就可以使用像Freemarker这样的模板引擎将出现占位符的地......
  • [连载]Java程序设计(05)---任务驱动方式:简单的加密/解密系统
    任务:还是上一家公司,现在该公司在全国各地都设立了自己的分公司以拓展其核心业务,那么就需要利用互联网在全国各地的公司之间传递信息(我们假定这些信息就是文字信息),这些信息可能涉及一些商业机密,为此公司需要一套简单的加密和解密系统来避免直接在互联网上传递明文信息。目前拟定了两......
  • 历史最全Java资源大全中文版整理分享
       很多程序员应该记得GitHub上有一个Awesome-XXX系列的资源整理。本资源对Java相关的资源列表进行翻译和整理,内容包括:构建工具、数据库、框架、模板、安全、代码分析、日志、第三方库、书籍、Java站点等。分享给需要的朋友。目录内容截图......
  • 第三次java博客
    在Java编程领域中,掌握如何读取和处理用户输入数据是非常基础和重要的一步。我们需要从用户那里获取输入数据,并根据输入数据进行相应的操作或计算。在这篇博客中,我们将会探讨如何在Java程序中读取和处理用户输入数据,以及如何利用这些数据来完成一些常见的任务,比如计算平均分和总成......