栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java自动装箱、拆箱、循环遍历与自动装箱的陷阱

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java自动装箱、拆箱、循环遍历与自动装箱的陷阱

java自动装箱、拆箱、循环遍历与自动装箱的陷阱 1. 自动装箱、拆箱、循环遍历
  • 编译之前的代码
package com.zhu.part10;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Demo10_11 {

    public static void main(String[] args) {


        //自动装箱
       List list = Arrays.asList(1, 2, 3, 4);

       int sum = 0;

       //自动拆箱,循环遍历
       for (int i : list) {
            sum += i;
       }
        System.out.println(sum);
    }
}

  • jdk8 编译之后的class文件中的代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.zhu.part10;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Demo10_11 {
    public Demo10_11() {
    }

    public static void main(String[] args) {
        List list = Arrays.asList(1, 2, 3, 4);
        int sum = 0;

        int i;
        for(Iterator var3 = list.iterator(); var3.hasNext(); sum += i) {
            i = (Integer)var3.next();
        }

        System.out.println(sum);
    }
}

  • 《深入理解java虚拟机》作者环境编译后的class文件
package com.zhu.part10;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;


public class Demo10_12 {
    public static void main(String[] args) {


        //转化成了对应的包装和还原方法:Integer.valueOf(),Integer.intValue()
        //变长参数,调用的时候使用了一个数组类型的参数
        List list = Arrays.asList(new Integer[] {
           Integer.valueOf(1),
           Integer.valueOf(2),
           Integer.valueOf(3),
           Integer.valueOf(4)
        });

        int sum = 0;

        //遍历循环则是还原成了迭代器去实现
        for (Iterator localIterator = list.iterator(); localIterator.hasNext();) {
            sum += ((Integer)localIterator.next()).intValue();
        }
        System.out.println(sum);

    }
}

在泛型中,自动装箱、拆箱转化成对应的包装和还原方法,比如自动装箱Integer.valueOf() 和自动拆箱 Integer.intValue()

我们可以重点查看自动装箱方法的源码,Integer.valueOf()

  
  //这个源码是个坑
  public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
  }


由此我们可以得到这样一个结论:Integer的默认缓存范围为-128到127,在自动装箱的时候,如果数字范围在-128到127,则直接返回缓存中已有的对象,不在这个范围之内则new一个新的对象。

这也就以下代码打印false的原因

Integer e = 321;
Integer f = 321;
System.out.println(e == f);

//打印false
2. 自动拆箱的陷阱
package com.zhu.part10;


public class Demo10_13 {
    public static void main(String[] args) {

        //Integer 是 int的包装类
        //Long 是 long的包装类


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


        //1、包装类的 "==" 运算在不遇到算数运算的时候不会自动拆箱,以及它们的equals()方法不处理数据类型转换
        System.out.println(c == d); //true

        //2、安照1中的思路应该就是true,但是此处也是一个小坑,上文中有详细解释
        System.out.println(e == f); //false

        //3、true 自动拆箱后的值和类型相等
        System.out.println(c == (a + b)); 

        //4、true 值和类型都相等
        System.out.println(c.equals(a + b));

        //包装类的 "==" 运算在不遇到算数运算的时候不会自动拆箱
        //5、a + b是算数运算 ,所以包装类拆箱,拆箱后两边数值相等,返回true
        System.out.println(g == (a + b));//true

        //6、包装类的equals()方法不处理数据类型转换,g和a+b的类型不同,所以返回false
        System.out.println(g.equals(a + b));

    }
}

一些方法技巧:

  • 我们可以在idea中查看java文件编译之后的class文件

  • 遇到问题我们可以通过查看源码的方式进一步发现和理解问题的所在

参考书籍:《深入理解java虚拟机》

如有错误和冒犯,欢迎指正。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021516.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号