当前位置: 首页 > news >正文

Java学习之旅第二季-10:包装类

10.1 何为包装类

我们已经了解到基本类型和引用类型之间无法进行赋值操作,甚至无法将基本数据类型值与对象引用进行比较。Java API中的某些部分仅能处理对象,例如,Java 中的集合仅能处理对象。我们无法创建包含基本数据类型值(如 1、2、3 和 4)的List。在将这些基本数据类型值存储到列表或集合中之前,就需要将它们封装成对象。

基本数据类型值与引用数据类型值之间的赋值不兼容的问题一致就存在于Java中。所以 Java API 在 java.lang 包中提供了八个类来表示八种基本类型中的某一种。这些类被称为包装类(Wrapper Class),因为它们会将一个基本数据类型的值封装起来,除此之外,Java 对其还有特殊的支持。

下表是基本数据类型与其对应包装类的对应关系,处理 int 和 char之外,其它类型的包装类名称只是将首字母改大写:

基本数据类型包装类
byteByte
intInteger
shortShort
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter

本小节只关注包装类作为数据类型的使用,而不过多关注它们提供的方法、

10.2 包装类的实例化

所有的包装类都是不可变的。它们提供了三种创建其对象的方法:

  • 使用构造方法(已弃用),自 Java 9 开始被标记为 Deprecated
  • 使用 valueOf() 工厂静态方法,有些包装类有两种重载形式,一个参数是基本数据类型,另一个字符串
  • 使用 parseXxx() 方法,其中 Xxx 是包装类的名称。该方法在 Character 类中不可用。

示例:

Integer num1 = new Integer(10);
Integer num2 = Integer.valueOf(10);
Integer num3 = Integer.valueOf("10");
Integer num4 = Integer.parseInt("10");Float num5 = Float.valueOf(1.23F);
Float num6 = Float.valueOf("1.23F");
Float num7 = Float.parseFloat("1.23F");
Double num8 = Double.valueOf(1.23);
Double num9 = Double.valueOf("1.23");
Double num10 = Double.valueOf("1.23");Character c1=Character.valueOf('a');Boolean b1 = Boolean.valueOf("true");
Boolean b2 = Boolean.parseBoolean("false");

有意思的一点是调用 Integer、Byte、Short 和 Long 的 valueOf 方法时,在内部会缓存一个对象,以Integer为例:

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] 之间时,会从缓存数组中获取对象,超出这个范围则创建新的对象。我们可以使用 == 运算符测试一下-

Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
System.out.println(a == b);         // 输出 true

如果将上面变量a 和 b 的值改大一点,情况就不同了:

Integer a = Integer.valueOf(128);
Integer b = Integer.valueOf(128);
System.out.println(a == b);         // 输出 false

因为 == 运算符用于引用数据类型之间的比较时,实际比较的是地址是否相同,即两个对象是不是同一个。所以从刚才的测试结果来讲,当把要传入 valueOf 方法的整型参数从127改为128时,返回的Integer实例就不是同一个了。其它的数据我就会不再测试了。大家可以自行测试,看范围是不是[-128~127]之间就是统一对象。

10.3 自动装箱与自动拆箱

所谓装箱(box)就是基本数据类型转换成对应的包装类;反之拆箱(unbox)是指包装类转换为对应的基本数据类型。

上面对包装类的实例化中,很多方法可以将基本数据类型数据转换为对应包装类实例,也就实现了装箱操作。如果要实现拆箱,也可以调用包装类提供的方法,下面以整型数据类型数据为例:

Integer num1 = Integer.valueOf(10);      // 装箱
int num2 = num1.intValue();              // 拆箱。 num2 的值是 10

从Java 5 开始,就引入了自动装箱与自动拆箱机制,用于在基本数据类型与对应的包装类之间自动互相转换,且该转换是在编译时执行,实际上编译之后是调用的静态方法valueOf。此时的代码就简洁很多了、

Integer num1 = 10;
int num2 = num1;

可以看到,基本数据类型与对应的包装类型之间可以自动进行转换,无需调用任何其他方法。

再论比较运算符

之前介绍比较运算符时提到,基本数据类型与引用数据类型之间不能进行比较,但是包装类除外。另外包装类之间也可以进行大小比较,此时会自动进行拆箱操作:

Integer num1 = Integer.valueOf(12);
System.out.println(num1 > 10);        // 输出 true
Integer num2 = 13;
System.out.println(num1 > num2);      // 输出 false

另外若包装类的实例值是自动装箱获得的,比较时需考虑缓存,例如:Integer,其范围默认是:[-128~127]

Integer num1 = 127;  
Integer num2 = 127; 
System.out.println(num1 == num2);  // 输出 trueInteger num3 = 128;  
Integer num4 = 128; 
System.out.println(num3 == num4);  // 输出 false

再论算术运算符

当有了自动拆箱之后,之前介绍到的算术运算符也有了新的使用场景:

Integer num3 = 1;
Integer num4 = 2;System.out.println(num3 + num4);    // 3
System.out.println(num3 - num4);    // -1
System.out.println(num3 * num4);    // 2
System.out.println(num3 / num4);    // 0
System.out.println(num3 * num4);    // 2

再论方法重载

如果有以下的两个重载方法,一个参数是int类型,另一个参数是Integer类型:

public class BoxUnboxDemo {public void print(int num) {System.out.println("print(int num)");}public void print(Integer num) {System.out.println("print(Integer num)");}
}

当使用如下实参调用时,会访问哪一个呢?结论应该很容易得出,会找形参与实参类型最匹配的方法:

BoxUnboxDemo demo=new BoxUnboxDemo();
demo.print(1);                                // 输出 print(int num)
demo.print(Integer.valueOf(1));               // print(Integer num)

假如只声明了一个方法呢?比如:

public class BoxUnboxDemo {public void print(int num) {System.out.println("print(int num)");}
}

此时两句调用都能成功吗?结果如下:

print(int num)
print(int num)

如果只保留另一个方法,

public class BoxUnboxDemo {public void print(Integer num) {System.out.println("print(Integer num)");}
}

调用代码不变,结果如下:

print(Integer num)
print(Integer num)

结论已经显而易见了,在没有找到形参与实参类型最匹配的方法时,会进行自动拆箱或装箱,然后找合适的方法调用。

null问题

在自动装箱与自动拆箱时,null有时会造成潜在的bug

Integer n = null;   // n 被赋值为 null 
int a = n;          // 运行时抛出空指针异常 NullPointerException

上面两句代码在编译时并不会出现语法错误,但是当程序运行起来后,会有异常抛出,这是因为 null 对象没有办法通过内部转换为对应的基本数据类型。

10.4 小结

本小节介绍了Java中的包装类,主要包含包装类的作用、8种基本类型对应的包装类及其实例化方式(构造方法、valueOf()、parseXxx()),特别说明Integer等类会对[-128,127]范围内的值进行缓存;自动装箱与拆箱机制:Java5开始支持基本类型与包装类之间的自动转换,并详细说明了在比较运算、算术运算和方法重载中的具体表现;另外指出null值在自动拆箱时会导致空指针异常,以及缓存机制对对象比较的影响。

http://www.dtcms.com/a/454564.html

相关文章:

  • h5网站开发框架网站搭建制作公司
  • 韦博在上面做课件的网站叫什么网站设计实施
  • 长沙律师网站建设淘宝客如何做免费的网站
  • 做网站公司需要帮客户承担广告法吗网站验收技术指标
  • 整体设计 逻辑系统程序 之16 从 “三阶三段三元” 拆解到核心层最小原型的落地推导与实践
  • 英德市住房城乡建设网站logo在线查询
  • 基于Kali linux 安装pyenv及简单使用方法及碰到的问题
  • 旅游网站开发背景意义没网站怎么做app
  • 【论文笔记】VisionPAD: A Vision-Centric Pre-training Paradigm for Autonomous Driving
  • phpcms 安装官网的教程更换域名后网站图片还是无法显示php网站超市源码下载
  • 【开题答辩全过程】以 爱家家具销售网为例,包含答辩的问题和答案
  • STM32G474单片机开发入门(五)ADC详解及实战
  • 网站重做 影响wordpress 页面 html
  • 页网站设计wordpress 繁体
  • 有哪些网站上可以做试卷视频网站怎么搭建
  • 网站开发需多少钱重庆医疗网站建设
  • 网站制作公司的宣传海报wordpress调用热门文章
  • 丹徒网站建设多少钱wordpress附件数据库
  • 怎样做网站上的语种链接哪个网站可以做图交易平台
  • 门户网站建设美丽装修设计网站哪个最好
  • 学校网站建设开题报告书怎么在网站上加qq
  • 免费做网站网站有人哪些qq推广群号码大全
  • 【Spring框架】——原理篇
  • 网站建设问题分类和排除方法分析建设一个网站的工作方案
  • 网站设计例子wordpress固定链接html
  • 营销型网站的建站步骤是什么意思推广引流网站
  • 计算机-网络基础
  • 企业cms建站免费制作个人网页
  • UVa 237 Monitoring Wheelchair Patients
  • Linux I2C 子系统