MENU

Java-31 包装类

September 29, 2023 • Read: 73 • Java阅读设置

面向对象编程

包装类

1 什么是包装类

包装类,简单地说就是基本数据类型所对应的类。

包装类能够将基本数据类型的数据包装成一个对象。该对象是其基本数据类型对应的包装类的对象。
包装类能够为其对象提供处理对应的基本数据类型数据有用的方法和属性。

2 包装类

数值型的基本数据类型对应的包装类有一个共同的直接父类,Number
2023-09-29T13:52:20.png

3 基本数据类型数据转换为包装类对象

1) 方法一:用对应包装类的构造器来构造基本数据类型数据对象

  • 所有包装类都有一个专门接收对应基本数据类型数据,以构造对应对象的构造器:public WrapClass(primitiveType value)
  • Character包装类外,其他所有包装类都有一个接收能够转换为对应基本数据类型数据的字符串,以构造对应对象的构造器:public WrapClass(String s)

    • 对于Number类,该构造方法会抛出NumberFormatException异常,表示传入的字符串s无法转换为对应数据类型数据。
    • 对于Boolean类,该构造方法不会抛出异常。其方法的字符串s如果是非null的、不区分大小写的true,则直接转换为true对应的对象,否则,都转换为false对应的对象。
  • Float包装类除了以上两种构造方法,还有一个用来接收double基本数据类型的参数,以构造对应对象的构造器。
    2) 方法二:自动装箱
  • 通常要实例化对象,就要按照类的构造器去new出一个对象,包装类对象也不例外。
    JDK 5.0后包装类具有了一个新特性:自动装箱,就是对于某个基本数据类型的数据,能够直接通过包装类的声明,以基本数据类型数据赋值,就能够直接将基本数据类型数据转换为包装类对象:WrapClass obj = primitiveValue
    可以理解为primitiveValue等价于new WrapClass(primitiveValue)

4 包装类对象转换为基本数据类型数据

包装类对象转换为基本数据类型数据的一个主要目的是,基本数据类型数据能够直接进行进行加减乘除运算。
1) 方法一:用对应包装类的返回相关基本数据类型数据的方法

  • 所有的包装类都有一个专门返回其对应基本数据类型数据的方法:public xxx xxxValue(),其中xxx表示对应的基本数据类型,比如Short包装类的该方法xxx就表示基本数据类型short
  • Number类除了有上述方法外,还有能够将该对象作为其他Number类对应的基本数据类型数据返回,该方法格式与上述方法格式一致,xxx代表着其他Number类对应的基本数据类型。
    简单地说,就是Number类对象能够利用xxxValue()方法返回成任何Number类对应的基本数据类型数据,也就是xxx可以是byte, short, int, long, float, double
    2) 方法二:自动拆箱
  • 通常要将包装类对象转换为对应的基本数据类型数据,要通过调用对应包装类的xxxValue方法。
    JDK 5.0后包装类具有了一个对应于自动装箱的新特性:自动拆箱,就是对于某个包装类对象,能够直接通过基本数据类型声明,以包装类对象赋值,就能够直接将包装类对象转换为基本数据类型数据:primitiveType data = WrapClassObj

5 基本数据类型数据或包装类对象与String之间的转换

这里之所以将基本数据类型数据包装类对象等同起来,因为它们之间可以自动装箱和自动拆箱,相当于间接等同。
1) 基本数据类型数据或包装类对象转换为String

  • 方式一:基本数据类型数据可以通过连接运算直接转换:primitiveValue + ""
  • 方式二:基本数据类型数据或包装类对象可以通过利用String的静态方法valueOf(xxx)来实现转换为String:String str = String.valueOf(xxx),所谓静态方法就是不用专门通过一个对象来使用该方法,直接用类名.即可。
    2023-09-30T14:18:44.png
  • 方式三:基本数据类型数据(通过自动装箱为包装类对象)或包装类对象可以通过使用包装类对应的toString()方法:WrapClass.toString()
    2) String转换为基本数据类型数据或包装类对象
  • String可以通过包装类对象对应的静态parseXXX(String s)方法来转换为XXX对应的基本数据类型数据,而基本数据类型数据可以通过自动装箱转换为包装类对象:public static xxx parseXXX(String s),其中xxx表示对应的基本数据类型。
  • Character包装类没有这个方法,因此无法通过这个上述方法来将String转换为char基本数据类型数据或者对应的包装类对象。
  • Integer, Byte, Short包装类中的上述方法会在参数s不能解析为对应基本数据类型数据时,抛出NumberFormatException异常,也就是说snull时也会抛出这个异常。
    2023-09-30T14:31:27.png
  • Float, Double包装类中的上述方法会在参数s不能解析为对应基本数据类型数据时,抛出NumberFormatException异常;在snull时会抛出NullPointerException异常。还有一些细节参照官方文档。
    2023-09-30T14:30:45.png
    2023-09-30T14:31:08.png

6 自动装箱与自动拆箱原理

通过反解码可知,包装类的自动装箱和自动拆箱机制的原理是:

  • 自动装箱:调用对应包装类中的静态方法:public static WrapClass valueOf(primitiveType value)
  • 自动拆箱:调用对应包装类中的转换为基本数据类型数据的方法:public xxxValue()
    2023-10-01T13:47:14.png

自动拆箱的xxxValue()方法前面已经介绍过。
自动装箱的valueOf(primitiveType value)方法结合官方文档和源码可知:

  • Byte, Short, Integer, Long包装类对应的该方法用于构造对应的基本数据类型数据的包装类对象比其包装类对应的构造器方法的时间和空间性能更好,因为该方法将常用的该基本数据类型的数据,即对应基本数据类型的-128~127,对应的包装类对象存放在了cache中。
    换句话说,用自动装箱来构造在cache中的包装类对象会直接引用cache中有的包装类对象,而不会new出新的对象,只有在cache中没有的,即常用数据范围外的数据对应的包装类对象,才会new出新的对象。
    而构造器方法是不论是否是常用数据对应的包装类对象,都会new出新的对象以构造出对象。
    2023-10-01T14:01:32.png
    2023-10-01T14:02:07.png
    2023-10-01T14:02:20.png
    2023-10-01T14:02:36.png

2023-10-01T14:03:05.png
2023-10-01T14:03:33.png

2023-10-01T14:03:54.png
2023-10-01T14:04:10.png
2023-10-01T14:04:27.png
2023-10-01T14:04:38.png

  • Float, Double包装类的该方法并没有cache常用数据,但仍然推荐使用自动装箱来实例化对象。
    2023-10-01T14:04:58.png
    2023-10-01T14:05:11.png
  • Boolean包装类对应的该方法也比其包装类对应的构造器构造对象更有效率,因为其包装类具有truefalse对应的静态属性,自动装箱对应的该方法就是直接引用对应的静态属性,也不是new出新的对象。
    2023-10-01T14:05:35.png
    2023-10-01T14:06:01.png
    2023-10-01T14:06:13.png
    2023-10-01T14:06:25.png
  • Character包装类的对应该方法也比其包装类对应的构造器构造对象更有效率,因为其将'\u0000' 到 '\u007F'范围的字符放到cache中了,也就是说这个范围中的字符对应的包装类对象直接从cache中引用,而不是new出新的对象。
    2023-10-01T13:59:48.png
    2023-10-01T14:00:18.png
    根据Unicode编码表可知,0000-007F:C0控制符及基本拉丁文 (C0 Control and Basic Latin),可以理解为键盘能打出的字符。
    2023-10-01T13:59:27.png
    2023-10-01T14:00:47.png
    2023-10-01T14:00:57.png
Last Modified: October 1, 2023