面向对象编程
包装类
1 什么是包装类
包装类,简单地说就是基本数据类型所对应的类。
包装类能够将基本数据类型的数据包装成一个对象。该对象是其基本数据类型对应的包装类的对象。
包装类能够为其对象提供处理对应的基本数据类型数据有用的方法和属性。
2 包装类
数值型的基本数据类型对应的包装类有一个共同的直接父类,Number
。
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)
,所谓静态方法就是不用专门通过一个对象来使用该方法,直接用类名.
即可。 - 方式三:基本数据类型数据(通过自动装箱为包装类对象)或包装类对象可以通过使用包装类对应的
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
异常,也就是说s
为null
时也会抛出这个异常。
Float, Double
包装类中的上述方法会在参数s
不能解析为对应基本数据类型数据时,抛出NumberFormatException
异常;在s
为null
时会抛出NullPointerException
异常。还有一些细节参照官方文档。
6 自动装箱与自动拆箱原理
通过反解码可知,包装类的自动装箱和自动拆箱机制的原理是:
- 自动装箱:调用对应包装类中的静态方法:
public static WrapClass valueOf(primitiveType value)
。 - 自动拆箱:调用对应包装类中的转换为基本数据类型数据的方法:
public xxxValue()
。
自动拆箱的xxxValue()
方法前面已经介绍过。
自动装箱的valueOf(primitiveType value)
方法结合官方文档和源码可知:
Byte, Short, Integer, Long
包装类对应的该方法用于构造对应的基本数据类型数据的包装类对象比其包装类对应的构造器方法的时间和空间性能更好,因为该方法将常用的该基本数据类型的数据,即对应基本数据类型的-128~127
,对应的包装类对象存放在了cache中。
换句话说,用自动装箱来构造在cache中的包装类对象会直接引用cache中有的包装类对象,而不会new
出新的对象,只有在cache中没有的,即常用数据范围外的数据对应的包装类对象,才会new
出新的对象。
而构造器方法是不论是否是常用数据对应的包装类对象,都会new
出新的对象以构造出对象。
Float, Double
包装类的该方法并没有cache常用数据,但仍然推荐使用自动装箱来实例化对象。Boolean
包装类对应的该方法也比其包装类对应的构造器构造对象更有效率,因为其包装类具有true
和false
对应的静态属性,自动装箱对应的该方法就是直接引用对应的静态属性,也不是new
出新的对象。Character
包装类的对应该方法也比其包装类对应的构造器构造对象更有效率,因为其将'\u0000' 到 '\u007F'范围的字符放到cache中了,也就是说这个范围中的字符对应的包装类对象直接从cache中引用,而不是new
出新的对象。
根据Unicode编码表可知,0000-007F:C0控制符及基本拉丁文 (C0 Control and Basic Latin),可以理解为键盘能打出的字符。