精华内容
下载资源
问答
  • 自动装箱和自动拆箱实现原理!

    千次阅读 2019-03-06 15:58:41
    什么是自动装箱和拆箱 自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是...

    什么是自动装箱和拆箱

    自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte, short, char, int, long, float, double 和 boolean 对应的封装类为Byte, Short, Character, Integer, Long, Float, Double, Boolean。

    下面例子是自动装箱和拆箱带来的疑惑

    
        public class Test {  
            public static void main(String[] args) {      
                test();  
            }  
        
            public static void test() {  
                int i = 40;  
                int i0 = 40;  
                Integer i1 = 40;  
                Integer i2 = 40;  
                Integer i3 = 0;  
                Integer i4 = new Integer(40);  
                Integer i5 = new Integer(40);  
                Integer i6 = new Integer(0);  
                Double d1=1.0;  
                Double d2=1.0;  
                  
                System.out.println("i=i0\t" + (i == i0));  
                System.out.println("i1=i2\t" + (i1 == i2));  
                System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));  
                System.out.println("i4=i5\t" + (i4 == i5));  
                System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));      
                System.out.println("d1=d2\t" + (d1==d2));   
                  
                System.out.println();          
            }  
        } 
    

    请看下面的输出结果跟你预期的一样吗?

    输出的结果:
    i=i0        true
    i1=i2       true
    i1=i2+i3    true
    i4=i5       false
    i4=i5+i6    true
    d1=d2     false

    为什么会这样?带着疑问继续往下看。

    自动装箱和拆箱的原理

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

    明白自动装箱和拆箱的原理后,我们带着上面的疑问进行分析下Integer的自动装箱的实现源码。如下:

    
        public static Integer valueOf(int i) {
            //判断i是否在-128和127之间,存在则从IntegerCache中获取包装类的实例,否则new一个新实例
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    
    
        //使用亨元模式,来减少对象的创建(亨元设计模式大家有必要了解一下,我认为是最简单的设计模式,也许大家经常在项目中使用,不知道他的名字而已)
        private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            //静态方法,类加载的时候进行初始化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() {}
        }
    

    Integer i1 = 40; 自动装箱,相当于调用了Integer.valueOf(40);方法。
        首先判断i值是否在-128和127之间,如果在-128和127之间则直接从IntegerCache.cache缓存中获取指定数字的包装类;不存在则new出一个新的包装类。
        IntegerCache内部实现了一个Integer的静态常量数组,在类加载的时候,执行static静态块进行初始化-128到127之间的Integer对象,存放到cache数组中。cache属于常量,存放在java的方法区中。
        如果你不了解方法区请点击这里查看JVM内存模型

    接着看下面是java8种基本类型的自动装箱代码实现。如下:

        //boolean原生类型自动装箱成Boolean
        public static Boolean valueOf(boolean b) {
            return (b ? TRUE : FALSE);
        }
    
        //byte原生类型自动装箱成Byte
        public static Byte valueOf(byte b) {
            final int offset = 128;
            return ByteCache.cache[(int)b + offset];
        }
    
        //byte原生类型自动装箱成Byte
        public static Short valueOf(short s) {
            final int offset = 128;
            int sAsInt = s;
            if (sAsInt >= -128 && sAsInt <= 127) { // must cache
                return ShortCache.cache[sAsInt + offset];
            }
            return new Short(s);
        }
    
        //char原生类型自动装箱成Character
        public static Character valueOf(char c) {
            if (c <= 127) { // must cache
                return CharacterCache.cache[(int)c];
            }
            return new Character(c);
        }
        
        //int原生类型自动装箱成Integer
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    
        //int原生类型自动装箱成Long
        public static Long valueOf(long l) {
            final int offset = 128;
            if (l >= -128 && l <= 127) { // will cache
                return LongCache.cache[(int)l + offset];
            }
            return new Long(l);
        }
    
        //double原生类型自动装箱成Double
        public static Double valueOf(double d) {
            return new Double(d);
        }
    
        //float原生类型自动装箱成Float
        public static Float valueOf(float f) {
            return new Float(f);
        }
    

    通过分析源码发现,只有double和float的自动装箱代码没有使用缓存,每次都是new 新的对象,其它的6种基本类型都使用了缓存策略。
        使用缓存策略是因为,缓存的这些对象都是经常使用到的(如字符、-128至127之间的数字),防止每次自动装箱都创建一次对象的实例。
        而double、float是浮点型的,没有特别的热的(经常使用到的)数据的,缓存效果没有其它几种类型使用效率高。(补充:一个范围内的整数是有明确的个数限制的,而浮点型则不同)

     

    下面在看下装箱和拆箱问题解惑。

        //1、这个没解释的就是true
        System.out.println("i=i0\t" + (i == i0));  //true
        //2、int值只要在-128和127之间的自动装箱对象都从缓存中获取的,所以为true
        System.out.println("i1=i2\t" + (i1 == i2));  //true
        //3、涉及到数字的计算,就必须先拆箱成int再做加法运算,所以不管他们的值是否在-128和127之间,只要数字一样就为true
        System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));//true  
        //比较的是对象内存地址,所以为false
        System.out.println("i4=i5\t" + (i4 == i5));  //false
        //5、同第3条解释,拆箱做加法运算,对比的是数字,所以为true
        System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));//true      
        //double的装箱操作没有使用缓存,每次都是new Double,所以false
        System.out.println("d1=d2\t" + (d1==d2));//false

    转载自:https://www.jianshu.com/p/0ce2279c5691

    展开全文
  • 什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。  一般我们要创建一个类的对象实例的时候,我们会这样:  Class a = new Class(parameter);  当我们...

    • 什么是自动装箱拆箱

    基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。 

    自动装箱是java编译器在java原生类型和对应的对象包装类型上做的自动转换。
    例如,把int 装换成 Integer double转换成Double等等。
    如果是反过来转换,那么叫做自动拆箱,也是编译器为我们做的事情。

    一般我们要创建一个类的对象实例的时候,我们会这样:

     Class a = new Class(parameter);

     当我们创建一个Integer对象时,却可以这样:

     Integer i = 100; (注意:不是 int i = 100; )

    实际上,执行上面那句代码的时候,系统为我们执行了:Integer i = Integer.valueOf(100);

    此即基本数据类型的自动装箱功能。

     
    • 基本数据类型与对象的差别 

    基本数据类型不是对象,也就是使用int、double、boolean等定义的变量、常量。

    基本数据类型没有可调用的方法。

    eg:  int t = 1;     t.  后面是没有方法滴。

     Integer t =1; t.  后面就有很多方法可让你调用了。

     
    • 什么时候自动装箱

    例如:Integer i = 100;

    相当于编译器自动为您作以下的语法编译:Integer i = Integer.valueOf(100);

     
    • 什么时候自动拆箱

      自动拆箱(unboxing),也就是将对象中的基本数据从对象中自动取出。如下可实现自动拆箱:

    1  Integer i  10 // 装箱 
    2    int  t  =  i;  // 拆箱,实际上执行了 int t = i.intValue();

      在进行运算时,也可以进行拆箱。 

    1  Integer i  10
    2  System.out.println(i ++ );

     

    • Integer的自动装箱

    复制代码
    //在-128~127 之外的数
    Integer i1 =200;
    Integer i2
    =200;
    System.out.println(
    "i1==i2: "+(i1==i2));
    // 在-128~127 之内的数
    Integer i3 =100;
    Integer i4
    =100;
    System.out.println(
    "i3==i4: "+(i3==i4));
    复制代码
        输出的结果是:
        i1==i2: false
    i3
    ==i4: true

     说明:

    equals() 比较的是两个对象的值(内容)是否相同。

    "==" 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等。

     

    前面说过,int 的自动装箱,是系统执行了 Integer.valueOf(int i),先看看Integer.java的源码:

    1
    2
    3
    4
    5
    6
    public  static  Integer valueOf( int  i) {
         if (i >= - 128  && i <= IntegerCache.high)   // 没有设置的话,IngegerCache.high 默认是127
             return  IntegerCache.cache[i +  128 ];
         else
             return  new  Integer(i);
    }

      

    对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象(并不是新建对象)

    所以范例中,i3 与 i4实际上是指向同一个对象。

    而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象,所以范例中,i1与i2 指向的是不同的对象。

    当然,当不使用自动装箱功能的时候,情况与普通类对象一样,请看下例:

     

    1  Integer i3  = new  Integer( 100 ); 
    2  Integer i4  = new  Integer( 100 ); 
    3  System.out.println( " i3==i4:  " + (i3 == i4)); // 显示false

     自动装箱和自动拆箱让开发者更容易写出清晰的代码,可读写也更强。

     没有那么多我们手动的去转换。

     下面的表列出了原生类型和对应的包装类,编译器在使用它们的时候会给我们自动做拆箱和装箱。


    Primitive typeWrapper class
    booleanBoolean
    byteByte
    charCharacter
    floatFloat
    intInteger
    longLong
    shortShort
    doubleDouble

    • String 的拆箱装箱

    先看个例子:

    复制代码
    1  String str1  = " abc " ;
    2  String str2  = " abc " ;
    3  System.out.println(str2 == str1);  // 输出为 true 
    4  System.out.println(str2.equals(str1));  // 输出为 true 
    5     
    6  String str3  = new  String( " abc " );
    7  String str4  = new  String( " abc " ); 
    8  System.out.println(str3 == str4);  // 输出为 false 
    9  System.out.println(str3.equals(str4));  // 输出为 true
    复制代码

        这个怎么解释呢?貌似看不出什么。那再看个例子。

    1  String d  = " 2 "
    2  String e  = " 23 " ;
    3  =  e.substring( 0 1 );
    4  System.out.println(e.equals(d));  // 输出为 true 
    5  System.out.println(e == d);  // 输出为 false
    第二个例子中,e的初始值与d并不同,因此e与d是各自创建了个对象,(e==d)为false 。

    同理可知,第一个例子中的str3与str4也是各自new了个对象,而str1与str2却是引用了同一个对象。


    接下来我们来看一下  怎么把一个String和一个原生的int连接起来的
    String s1 = "Four"+4;

    为了看看Java编译器在背后到底做了什么,我们用javap -c来查看一下字节码。

       0:   ldc     #2; //String Four4
       2:   astore_1
       3:   iconst_4
       4:   istore_2
       5:   new     #3; //class java/lang/StringBuilder
       8:   dup
       9:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
       12:  ldc     #5; //String Four
       14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
    String;)Ljava/lang/StringBuilder;
       17:  iload_2
       18:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(I)Ljava/lan
    g/StringBuilder;
       21:  invokevirtual   #8; //Method java/lang/StringBuilder.toString:()Ljava/la
    ng/String;
       24:  astore_3
       25:  return
    从上面我们可以看到,编译器在做   "Four" + i的时候实际上相当于 new StringBuilder().append("Four").append(i).toString()





    参考

      http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html

      https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

    展开全文
  • 装箱拆箱,自动装箱和自动拆箱 以Integer的创建为例。 装箱拆箱 装箱:把基本数据类型转换成包装类对象(int—>Integer) Integer num1=new Integer(17); 拆箱:把一个包装类的对象,转换成基本类型的变量...

    装箱和拆箱,自动装箱和自动拆箱

    以Integer的创建为例。

    装箱和拆箱

    装箱:把基本数据类型转换成包装类对象(int—>Integer)

    Integer num1=new Integer(17);
    

    拆箱:把一个包装类的对象,转换成基本类型的变量(Integer—>int)

    int num2=num1.intValue();
    

    自动装箱和自动拆箱

    自动装箱:

    Integer num3=17;
    

    自动拆箱:

    int num4=num3;
    

    自动装箱和拆箱操作又是一个“语法糖”,只是编译器级别的新特性。 在底层依然是手动的拆箱和装箱。

    装箱的具体实现

    Integer num=new Integer("132");
    //调用了构造器,在构造其中可以把String转化为Integer的parseInt()
    System.out.println(num);
    //Integer num6="18";没有调用构造器所以不可以
    

    integer的构造方法:

    public Integer(String s) throws NumberFormatException {
            this.value = parseInt(s, 10);
        }
    

    可以看到里面的parseInt方法就是将Integer(“132”)里的字符串转换为int类型的数的主要方法。

    展开全文
  • 自动装箱和自动拆箱

    2019-07-17 13:42:56
    自动装箱和自动拆箱的问题 昨天老师讲了包装类,学习的目标是要理解自动装箱和自动拆箱的原理,老师留了个课后作业,题目如下: public class demo { public static void main(String[] args) { Integer a1 = 127; ...

    自动装箱和自动拆箱的问题

    昨天老师讲了包装类,学习的目标是要理解自动装箱和自动拆箱的原理,老师留了个课后作业,题目如下:

    public class demo {
        public static void main(String[] args) {
            Integer a1 = 127;
            Integer a2 = 127;
            Integer b1 = 128;
            Integer b2 = 128;
            System.out.println(a1 == a2);      //true
            System.out.println(b1 == b2);      //false
        }
    }
    

    答案第一个输出的为什么是·true呢?或许你会有这样的疑问,Integer不是包装类嘛,不是应该存在堆内存中嘛,为什么a1 == a2 是true这样,其实这里就包含了自动装箱和自动拆箱的原理。

    1.什么是自动装箱?
    自动装箱:将基本数据类型自动转成包装类
    如 :

       		Integer a = 127;
       	 //实际上是做了如下操作:
       		Integer a = Integer.valueOf(127);
    

    2.什么是自动拆箱?
    自动拆箱:将包装类自动转成基本数据类型
    如:

            Integer a= 127;
            int b = a;         //自动拆箱
    	//实际上是:
            Integer a = Integer.valueOf(3);
            int b = a.intValue();
    

    我们可以用反编译工具看看是不是这样的,把编译运行后的demo.class文件拖到反编译工具,代码如图:
    在这里插入图片描述
    接下来我们可以查看Integer的valueof的底层源码,注释的意思是:“该方法将始终缓存-128到127范围内的值(包括),并且可能缓存此范围之外的其他值。”

         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         *
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        @HotSpotIntrinsicCandidate
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    

    1、a1和a2会进行自动装箱,执行了valueOf函数,它们的值在-128-127]这个范围内,然后会返回 IntegerCache.cache[i + (-IntegerCache.low)],也就是写入缓存,a1和a2引用到了同一个Integer对象,所以它们肯定是相等的。

    2、b3和b4也进行自动装箱,执行了valueOf函数,它们的值大于128,所以会执行new Integer(128),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。

    由此我们可以得知结果了,步骤其实不难理解,就只是进行了隐式装箱,然后查看Integer的valueOf方法的源码就清楚了。

    展开全文
  • 一、什么是自动装箱和自动拆箱自动装箱: Java自动将基本数据类型封装为对象类型。 基本数据类型可以直接赋值给对应的包装类变量。如: Integer i = 100; 本质上是,编译器执行了Integer i = Integer.valueOf...
  • JDK5新特性:自动装箱和自动拆箱

    千次阅读 2018-02-06 14:39:45
    简单了解了一下java的思想语法,掌握一些工作中经常用到的知识(常用的数据结构、IO流、多线程、数据库、框架等等) 工作几年后再来看一遍Java知识,你会更关注一些细节,有更多的思考,掌握一些解决问题的思想。 ...
  • 包装类的自动装箱和自动拆箱是JDK1.5的新特性 在学习包装类的使用的时候,会学习到装箱(boxing)拆箱(unboxing),看下面的代码: int i = 10; //装箱操作,建一个Integer类型对象,将i的值放入对象的某个属性中 ...
  • 所谓自动装箱就是Integer是对象类型,而int是基本数据类型类型。所以“Integer i1=10”这种写法在理论上是不可以的。正确的写法应该是"Integer i1=Integet.valueOf...同理自动拆箱也就是把Integer对象可以直接赋值给i
  • 自动装箱:将基本数据类型重新转化为对象 public class Test { public static void main(String[] args) { // 声明一个Integer对象,用到了自动的装箱:解析为:Integer num = Integer.valueOf(9); Integer ...
  • Java 自动装箱和自动拆箱注意的问题

    千次阅读 2016-06-15 17:00:48
    自动装箱和自动拆箱不是什么复杂的技术,自动装箱就是基本类型(int,long)数据可以先自动转换为对应的封装类(Integer,Long)对象,而自动拆箱相反。 在本文中,笔者向大家介绍下Java中一个非常重要也非常有趣的...
  • 自动装箱和自动装箱 自动装箱是基本数据类型向包装类型转换的过程,自动拆箱是包装类型向基本数据类型转换的过程。 int i = 5; Interger j = i; //在这里,i为int数据类型,而Integer是int的包装类 int i2 = j; //...
  • 什么是自动装箱和自动拆箱
  • //true a自动拆箱成int类型,再c比较 实际上,当执行语句②时,系统为我们执行了: Integer i = Integer.valueOf(100);此也就是基本数据类型的自动装箱功能; 执行语句③时,实际执行了int t = i.intValue();自动...
  • Java自动装箱和拆箱的实现原理

    千次阅读 2019-10-02 10:02:31
    一、装箱拆箱 原始类型转换为对象类型就是装箱,反之就是拆箱。 原始类型byte,short,char,int,long,float,double,...自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intV...
  • 如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这…这…知识盲区… 回到家后小伟赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢… 别问结果,问就是没过...
  • Java自动装箱自动拆箱(包装类)

    千次阅读 多人点赞 2019-06-15 10:18:39
    时候,系统可以 自动将它“包装”为相应的包装类的实例程序需要对象时, 如果给的只是一个基本类型的值, 系统会将它自动装箱为包装类的实例达到的效果: 有了自动装箱之后, 基本类型的值可以当成对象用—— 其实是...
  • java 自动装箱拆箱 这些概念是jdk1.5以后新出的内容 java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱); 自动装箱就可以简单的理解为将基本...
  • 自动装箱和自动拆箱蜜糖—陷阱 先抛出问题,直接上代码 package com.xz.test; public class Test { public static void main(String[] args) { Integer num1 = 127; Integer num2 = 127; System.out.println...
  • 转载于 ...自动拆箱装箱是从JDK1.5开始才有的特性,其实它主要就是指基本类型与包装类的自动转换。如int 与Integer类型。 int 是基本类型,而Integer是int的包装类,在JDK1.5之前,int类...
  • 自动装箱 基本数据类型转换成包装类 自动拆箱 将包装类转成基本数据类型 参考图 案例 //自动装箱:这样定义系统转成Integer i = Integer.valueOf(100); Integer i= 100; //自动拆箱:这样定义系统转成 int ...
  • 什么是自动拆箱和自动装箱

    千次阅读 2019-12-25 20:28:02
    什么是自动拆箱和自动装箱 Java中基本类型有八种,可以分为四类: 整形: byte(一个字节来存储,范围为-2^7— 2^7-1), short (两个字节来存储,范围为-2^15— 2^15-1), int(四个字节来存储, -2^31— 2^31-1) ,...
  • 文章目录1 自动装箱和自动拆箱2 包装类还可以实现基本类型字符串之间的转换3 包装类可以与基本类型比较4 一个容易出错的情况 1 自动装箱和自动拆箱 自动装箱: 允许将一个基本类型数据直接赋值给一个它对应的...
  • 自动装箱和拆箱的了解,绝大多数程序员都知道会进行自动的装箱和拆箱,装箱和拆箱会影响性能。但是具体什么场景下会装箱,什么场景下会拆箱?装箱和拆箱的底层原理是啥?装箱和拆箱在什么哪个阶段进行? 问题 ...
  • 什么是自动装箱和自动拆箱自动装箱就是Java自动将原始值类型转变为对应的对象,如int 自动转变为Integer的过程。 自动拆箱则反之。 Java是怎么实现自动装箱和拆箱的? 测试代码如下: public class AutoPacking {...
  • 1.Integer是int的包装类,int则是java的一种基本数据类型。 2.Integer变量必须实例化后才能使用,int则不需要。 3.Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象...5.Integerin...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,735
精华内容 17,894
关键字:

自动装箱和自动拆箱