• java中基本数据类型和包装类自动装箱和拆箱


    自动装箱拆箱要点

      自动装箱时编译器调用valueOf将原始类型值转换成对象,看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对象.

    同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值。

      public int intValue() {
            return value;
        }

    何时发生自动装箱和拆箱

      自动装箱和拆箱在Java中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动讲这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向ArrayList这样的容器中增加原始类型数据时或者是创建一个参数化的类,比如下面的ThreadLocal。

    ArrayList<Integer> intList = new ArrayList<Integer>();
    intList.add(1); //autoboxing - primitive to object
    intList.add(2); //autoboxing
    
    ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
    intLocal.set(4); //autoboxing
    
    int number = intList.get(0); // unboxing
    int local = intLocal.get(); // unboxing in Java

    要注意的事项

      这是一个比较容易出错的地方,”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。看一个能说明问题的例子。

    public class AutoboxingTest {
    
        public static void main(String args[]) {
    
            // Example 1: == comparison pure primitive – no autoboxing
            int i1 = 1;
            int i2 = 1;
            System.out.println("i1==i2 : " + (i1 == i2)); // true
    
            // Example 2: equality operator mixing object and primitive
            Integer num1 = 1; // autoboxing
            int num2 = 1;
            System.out.println("num1 == num2 : " + (num1 == num2)); // true
    
            // Example 3: special case - arises due to autoboxing in Java
            Integer obj1 = 1; // autoboxing will call Integer.valueOf()
            Integer obj2 = 1; // same call to Integer.valueOf() will return same
                                // cached Object
    
            System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true
    
            // Example 4: equality operator - pure object comparison
            Integer one = new Integer(1); // no autoboxing
            Integer anotherOne = new Integer(1);
            System.out.println("one == anotherOne : " + (one == anotherOne)); // false
    
        }
    
    }
    
    Output:
    i1==i2 : true
    num1 == num2 : true
    obj1 == obj2 : true
    one == anotherOne : false

    值得注意的是第三个小例子,这是一种极端情况。obj1和obj2的初始化都发生了自动装箱操作。但是处于节省内存的考虑,加载Integer.class文件的时候会通过静态代码块中缓存-128到127的Integer对象。因为obj1和obj2实际上是同一个对象。所以使用”==“比较返回true。

    看源码

     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;
           //通过循环创建-128到127的对象,放到cache[] 中,当调用Integer.valueOf(-127到128之间的数),会返回相同的对象,其他的数直接调用 new Integer(i) 创建新的对象
    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; }

     最后看下面的测试类

    public class Test {
        public static void main(String[] args) {
            Integer i = 500;
            System.out.println(i == 500);
        }
    }

    返回为 true .说明 i 发生了拆箱操作,500 并没有发生装箱操作.如果发生装箱操作 Integer.valueOf(500) ,会产生一个新的对象,通过 == 比较会返回false.所以得出结论:

    基本类型和包装类进行 == 比较时,包装类进行拆箱操作,比较的是基本类型的值

  • 相关阅读:
    win10如何在局域网中设置一台电脑的固定ip地址
    智能电视软件安装(WIFI上网)
    路由器连接宽带(成功上网步骤方法)
    FastReport.Net使用:[5]主从表
    FastReport.Net使用:[4]分组
    FastReport.Net使用:[3]简单报表一
    FastReport.Net使用:[2]添加MSSQL数据源一
    FastReport.Net使用:[1]屏蔽打印对话框
    如何配置FastReport.Net环境
    如何安装使用FastReport
  • 原文地址:https://www.cnblogs.com/stevehu1231/p/9470613.html
Copyright © 2020-2023  润新知