千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > Java支持的数据类型有哪些?什么是自动拆装箱?

Java支持的数据类型有哪些?什么是自动拆装箱?

来源:千锋教育
发布人:qyf
时间: 2022-06-07 11:44:00 1654573440

java1

  这个题目需要咱们知道点字节码,因为大家都知道,很简单的东西,那他为啥还问你,那肯定希望你回答出来点内在东西:

  什么是自动装箱,拆箱

  先抛出定义,Java中基础数据类型与它们的包装类进行运算时,编译器会自动帮我们进行转换,转换过程对程序员是透明的,这就是装箱和拆箱,装箱和拆箱可以让我们的代码更简洁易懂

  Java中基础数据类型与它们对应的包装类见下表(共8种):

01

  当表格中左边列出的基础类型与它们的包装类有如下几种情况时,编译器会自动帮我们进行装箱或拆箱.

  进行 = 赋值操作(装箱或拆箱)

  进行+,-,*,/混合运算 (拆箱)

  进行>,<,==比较运算(拆箱)

  调用equals进行比较(装箱)

  ArrayList,HashMap等集合类 添加基础类型数据时(装箱)

  我们看一段平常很常见的代码:

public void testAutoBox() {

    List<Float> list = new ArrayList<>();

    list.add(1.0f);

    float firstElement = list.get(0);

}

  list集合存储的是Float包装类型,我传入的是float基础类型,所以需要进行装箱,而最后的get方法返回的是Float包装类型,我们赋值给float基础类型,所以需要进行拆箱,很简单,安排的明明白白

  具体自动装箱,拆箱,代码是如何实现的

  既然编译器帮我们自动进行了装箱,拆箱,那么编译器到底做了些什么,要搞清楚这些,最简单直接的方式就是看类经过编译器编译后的字节码,下面是上面一段代码的字节码实现

public testAutoBox()V

   L0

    LINENUMBER 15 L0

    NEW java/util/ArrayList

    DUP

    INVOKESPECIAL java/util/ArrayList.<init> ()V

    ASTORE 1

   L1

    LINENUMBER 16 L1

    ALOAD 1

    FCONST_1

    INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;

    INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z

    POP

   L2

    LINENUMBER 17 L2

    ALOAD 1

    ICONST_0

    INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object;

    CHECKCAST java/lang/Float

    INVOKEVIRTUAL java/lang/Float.floatValue ()F

    FSTORE 2

   L3

    LINENUMBER 18 L3

    RETURN复制代码

  · L0,对应我们代码的第一行,new了一个ArrayList,并赋值给了1号引用(就是list)。

  · L1,先加载list到栈顶,然后FCONST_1指令就是从常量池加载1.0f浮点数并压入栈顶(这一块知识,见附录1),然后调用了Float类的静态 valueOf方法,进行装箱

  · ,然后调用list的add方法。

  · L2,先加载list到栈顶,从常量池获取0(float,int,long,double等基础类型初始值都是0),调用list的get方法,检查是否能转换,调用了Float的floatValue方法,进行拆箱

  · ,存储得到的浮点数。

  所以结果很明显了,以float和Float为例,装箱就是调用Float的valueOf方法new一个Float并赋值,拆箱就是调用Float对象的floatValue方法并赋值返回给float。其他基础类型都是大同小异的,具体可以查看源码。

  ##自动装箱、拆箱中的坑 ###面试题中经常会有考点就是考察面试者对Java中自动装箱、拆箱是否了解透彻,比如下面这一道面试题?

public void testAutoBox2() {

    //1

     int a = 100;

     Integer b = 100;

     System.out.println(a == b);

     //2

     Integer c = 100;

     Integer d = 100;

     System.out.println(c == d);

     //3   

     c = 200;

     d = 200;

     System.out.println(c == d);

}

  请问执行结果是多少?题目很常见,我们来分析一下:

  第1段代码,基础类型a与包装类b进行==比较,这时b会拆箱,直接比较值,所以会打印 true

  第2段代码,二个包装类型,都被赋值了100,所以根据我们之前的解析,这时会进行装箱,调用Integer的valueOf方法,生成2个Integer对象,引用类型==比较,直接比较对象指针,这里我们先给出结论,最后会分析原因,打印 true

  跟上面第2段代码类似,只不过赋值变成了200,直接说结论,打印 false

1

  结果是不是很诡异,我们直接去看Integer类valueOf方法的实现(JDK8的实现) 

public static Integer valueOf(int i) {

    if (i >= IntegerCache.low && i <= IntegerCache.high)

        return IntegerCache.cache[i + (-IntegerCache.low)];

    return new Integer(i);

}

  可以看到,这里的实现并不是简单的new Integer,而是用IntegerCache做一个cache,cache的range是可以配置的

private static class IntegerCache {

  static final int low = -128;

  static final int high;

  static final Integer cache[];

  static {

  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++);

  这是IntegerCache静态代码块中的一段,默认Integer cache 的下限是-128,上限默认127,可以配置,所以到这里就清楚了,我们上面当赋值100给Integer时,刚好在这个range内,所以从cache中取对应的Integer并返回,所以二次返回的是同一个对象,所以==比较是相等的,当赋值200给Integer时,不在cache 的范围内,所以会new Integer并返回,当然==比较的结果是不相等的。

  附录1:JVM字节码整型的入栈指令有4个,分别是:

iconst(0~5分别对应iconst_0、iconst_1、iconst_2、iconst_3、iconst_4、iconst_5,-1对应iconst_m1)

bipush (-128~127)

sipush (-32768~32767)

ldc (-2147483648~2147483647)


  更多关于“Java培训”的问题,欢迎咨询千锋教育在线名师。千锋已有十余年的培训经验,课程大纲更科学更专业,有针对零基础的就业班,有针对想提升技术的好程序员班,高品质课程助理你实现java程序员梦想。

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT