网站模板如何优化,聊城网站优化网络推广,免费行情软件下载大全,手机网站大全网站title: “java 自动装拆箱” tags:
Java 将基本数据类型封装成对象的过程叫做装箱#xff08;boxing#xff09;#xff0c;反之基本数据类型对应的包装类转换为基本数据类型的过程叫做拆箱#xff08;unboxing#xff09;; 基本数据类型与其他对象的区别
基本数据类型 …
title: “java 自动装拆箱” tags:
Java 将基本数据类型封装成对象的过程叫做装箱boxing反之基本数据类型对应的包装类转换为基本数据类型的过程叫做拆箱unboxing; 基本数据类型与其他对象的区别
基本数据类型
Java是一门面向对象的强类型语言但它又不像python那样一切皆对象Java中有一部分使用最频繁的数据结构并不是面向对象的他们就是基本数据类型也叫内置类型他们在栈中储存比起其他用new创建的对象更加高效Java有9中基本数据类型分为五类
类型标识符备注整型byte, short, int, long浮点float, dauble字符char布尔boolean空void不能操作
基本数据类型的范围
整型的范围
byte 占一个字节也就是8位最高一位作为符号位有效位只有7位采用补码存储。
最大值0111 1111127
最小值1000 0000-128怎么算的 最高一位是符号位这是固定的正数用0表示负数用1表示然后后面的七位最大是7个1最小是7个0这就是用补码表示的byte能表示的最大最小数把补码转换为原码正数的补码就是源码负数的补码变源码取反加一然后转换为10进制。 short占两个字节16位有效15位
最大值2^15 -1: 32,767
最小值-(2^15): -32,768int: 占4个字节最大值【2^31 - 1】(2,147,483,647), 最小值【-2^31】(-2,147,483,648)long: 占8字节最大值【2^63 - 1】(9,223,372,036,854,775,807)最小值【-2^63】(-9,223,372,036,854,775,808)
包装类型
Java中其他的对象都是继承自object的有自己的属性和方法为了方便基本基本数据类型和其他对象的的操作Java为每个基本数据类型提供了对应的包装类型
基本数据类型包装类byteBytebooleanBooleanshortShortcharCharacterintIntegerlongLongfloatFloatdoubleDouble
为什么要使用包装类型
Java是一门面向对象的语言大部分操作都是针对对象的比如容器容器中能存入的最大的范围就是object而基本数据类型不属于对象那他就无法存入容器为了解决这个问题必须把基本数据类型“包装”起来让他作为一个对象参与到编程中。
装箱和拆箱
把基本数据类型包装成对象的过程叫做装箱反之把对象转换为基本数据类型的过程叫做拆箱。 Java SE5 后为了简化开发提供了自动装拆箱机制Java会在适当时刻自动转换基本数据类型和包装类型如
public class Demo1 {public static void main(String[] args) {Integer integer 3; // 自动装箱int i integer; // 自动拆箱}
}通过Javap反编译得到 public static void main(java.lang.String[]);Code:0: iconst_31: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: aload_16: invokevirtual #3 // Method java/lang/Integer.intValue:()I9: istore_210: return在自动装箱时其实是调用了包装类的valueOf()方法而在自动拆箱时则调用了包装类的intValue()方法所以如果在JavaSE5之前没有自动装拆箱机制上面的代码我们需要这样写
public class Demo1 {public static void main(String[] args) {Integer integer Integer.valueOf(3); // 装箱int i Integer.intValue(integer); // 拆箱}
}除int和Integer之外,其他基本类型和包装类的自动转换也一样装箱时调用valueOf()方法拆箱时调用xxxValue()方法。
什么时候自动装箱
1. 初始化赋值函数返回时
当把基本数据类型赋值给包装类时或者基本数据类型作为函数返回值但函数声明要求返回包装类型时会自动装箱如上面的例子
2. 将基本数据类型放入容器中
public void func2(){ListInteger list new ArrayList();list.add(1);}反汇编之后 public void func2();Code:0: new #4 // class java/util/ArrayList3: dup4: invokespecial #5 // Method java/util/ArrayList.init:()V7: astore_18: aload_19: iconst_110: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;13: invokeinterface #6, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z18: pop19: return在第10步使用了自动装箱
什么时候自动拆箱
1. 初始化赋值函数返回时
把包装类对象赋值给基本数据类型的变量时会自动拆箱函数返回值原理一样
2. 包装类型做算数运算时
算数运算包括比较大小是针对基本数据类型的所以无论是基本数据类型与包装类型还是包装类型与包装类型之间做运算都会转换成两个基本数据类型
public void func3(){Integer integer 3;int i 1;Integer integer1 1;boolean b1 integer i; // 基本数据类型与包装类型比较大小boolean b2 integer integer1; // 两个包装类型比较大小}反汇编后
public void func3();Code:0: iconst_31: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: iconst_16: istore_27: iconst_18: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;11: astore_312: aload_113: invokevirtual #3 // Method java/lang/Integer.intValue:()I16: iload_217: if_icmple 2420: iconst_121: goto 2524: iconst_025: istore 427: aload_128: invokevirtual #3 // Method java/lang/Integer.intValue:()I31: aload_332: invokevirtual #3 // Method java/lang/Integer.intValue:()I35: if_icmple 4238: iconst_139: goto 4342: iconst_043: istore 545: return通过13步说明基本数据类型与包装类型比较大小会转换为两个基本数据类型再比较 通过2832步说明两个包装类型比较大小也会转换为基本数据类型
普通的加减乘除也一样
public void func4() {Integer integer 3;int i 1;Integer integer1 1;int s integer integer1;int s1 integer i;}public void func4();Code://...13: invokevirtual #3 // Method java/lang/Integer.intValue:()I16: aload_317: invokevirtual #3 // Method java/lang/Integer.intValue:()I20: iadd21: istore 423: aload_124: invokevirtual #3 // Method java/lang/Integer.intValue:()I//...3. 三目运算
如果三目运算的第二三位一个是基本数据类型另一个是包装类型时会自动拆箱成两个基本数据类型
public void func5() {boolean flag true;Integer i 8;int j;j 3;int k flag ? i: j;
}public void func5();Code:0: iconst_11: istore_12: bipush 84: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;7: astore_28: iconst_39: istore_310: iload_111: ifeq 2114: aload_215: invokevirtual #3 // Method java/lang/Integer.intValue:()I18: goto 2221: iload_322: istore 424: return因为i是包装类型j是基本数据类型所以在14行把i自动拆箱成了基本数据类型并不是应为三目运算返回的是int所以做三目运算时应该注意尤其是基本数据类型和对象混杂时如果对象没被赋值可能导致NPL空指针异常 只有一个是基本数据类型一个是包装类对象时才会自动拆箱两个对象是不拆的。 装箱和拆箱时的缓存问题
public class Demo2 {public static void main(String[] args) {Integer a1 1;Integer a2 1;int a3 1;System.out.println(a1 a2); // trueSystem.out.println(a1.equals(a2)); // trueSystem.out.println(a1 a3); // trueSystem.out.println(a1.equals(a3)); // true}
}public class Demo2 {public static void main(String[] args) {Integer a1 133;Integer a2 133;int a3 133;boolean b1 a1 a2;boolean b2 a1.equals(a2);boolean b3 a1 a3;boolean b4 a1.equals(a3);System.out.println(b1); // falseSystem.out.println(b2); // trueSystem.out.println(b3); // trueSystem.out.println(b4); // true}
}两次结果不同原因就是自动拆装箱时存在缓存问题当我们第一次使用Integer时Java会初始化一个Integer[] cache然后通过循环把-128到127之间的数加入到这个缓存中如果新new的Integer的值在这个范围内就直接返回这个创建好的对象equals()比较值比较是不是同一对象所以不管怎样equals的结果都是true,而在-128 到 127 之间是true超出这个范围是false。 这个就类似于python中的小整数池但python的范围是[-5, 256] 除[-128, 127]之间的整数外boolean的两个值以及\u0000至 \u007f之间的字符也在常量池中。
总结
什么是包装类
为了方便操作基本数据类型对每一种基本类型提供一个包装类他们将基本数据类型包装成一个对象
什么是装箱拆箱
把基本数据类型包装成包装类的过程叫装箱使用包装类的valueOf()方法 把包装类转换为基本数据类型的过程叫拆箱使用包装类的xxxValue()方法
什么是自动装箱/拆箱
Java SE5 引入的一种在特定情况下将基本数据类型自动转换为包装类/包装类自动转换为基本数据类型 的机制 什么时候自动装箱 Integer a 5 函数返回值 把基本数据类型加入容器时 什么时候自动拆箱 初始化赋值 函数返回值 三目运算第二第三个参数既有包装类也有基本数据类型时 算术运算比较大小 什么是自动拆装箱时的缓存
第一次使用某些包装类时Java会创建一个缓存池以后每次需要包装类对象就先会找缓存池中有没有有就直接返回没有才创建。缓存池的范围
整型[-128, 127] 布尔[true, false] 字符[\u0000, \u007f]
参考
什么是Java中的自动拆装箱 Java中整型的缓存机制