共计 2148 个字符,预计需要花费 6 分钟才能阅读完成。
1、基本数据类型包装类
Java 中每一种基本类型都会对应一个唯一的包装类,基本类型与其包装类都可以通过包装类中的静态或者成员方法进行转换。每种基本类型及其包装类的对应关系如下,值得注意的是,所有的包装类都是 final 修饰的,也就是它们都是无法被继承和重写的。
2、包装类常用方法
从源代码的角度来看,基础类型和包装类型都可以通过赋值语法赋值给对立的变量类型,如下面的代码所示。
Integer a = 1; | |
int a = new Integer(1); |
这种语法是可以通过编译的。但是,Java 作为一种强类型的语言,对象直接赋值给引用类型变量,而基础数据只能赋值给基本类型变量,这个是毫无异议的。那么基本类型和包装类型为什么可以直接相互赋值呢?这其实是 Java 中的一种“语法糖”。
“语法糖”是指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会(来自百度百科)。
换句话说,这其实是一种障眼法,那么实际上是怎么样的呢?
Integer a = 1; | |
其实相当于 | |
Integer a = Integer.valueOf(1); |
其他的包装类都是类似的,下表是所有包装类中的类型转换方法。
public class BzDemo {public static void main(String args[]) {// 定义整型对象 i | |
Integer i = new Integer(100); | |
// 定义浮点型对象 d | |
Double d = new Double("123.456"); | |
//i,d 转换为 int 类型 | |
int j = i.intValue() + d.intValue(); | |
//i,d 转换为 float 类型 | |
float f = i.floatValue() + d.floatValue(); | |
System.out.println(j); | |
System.out.println(f); | |
// 将字符串,转换为 double | |
double pi = Double.parseDouble("3.1415926"); | |
// 将字符串,转换为 Double | |
double r = Double.valueOf("2.0").doubleValue(); | |
double s = pi * r * r; | |
System.out.println(s); | |
try {// 将字符串,转换为 int | |
int k = Integer.parseInt("1.25"); | |
} catch (NumberFormatException e) {System.out.println("数据格式不对"); | |
} | |
// 十进制转二进制 | |
System.out.println(Integer.toBinaryString(123) + "B"); | |
// 十进制转十六进制 | |
System.out.println(Integer.toHexString(123) + "H"); | |
// 十进制转八进制 | |
System.out.println(Integer.toOctalString(123) + "O"); | |
} | |
} |
运行结果:
3、装箱与拆箱
3.1、装箱
装箱就是 java 自动将原始类型值转换成对应的对象,比如将 int 的变量转换成 Integer 对象,这个过程叫做装箱。
自动装箱时编译器调用 valueOf()将原始类型值转换成对象。
3.2、拆箱
拆箱就是 java 自动将对应的对象转换成原始类型值,比如将 Integer 对象转换成 int 的变量,这个过程叫做拆箱
自动拆箱时,编译器通过调用类似 xxxValue()这类方法 (如:intValue(),doubleValue()) 将对象转换成原始类型值。
3.3、什么时候会产生装箱与拆箱
3.3.1、赋值时
需要手动地进行类型转换,而现在所有的转换都是有编译器来完成。
Integer iObject = Integer.valueOf(3); | |
int iPrimitive = iObject.intValue(); | |
Integer iObject = 3; | |
int iPrimitive = iObject; |
3.3.2、方法调用时
当在进行方法调用时,可以传入原始数据值或对象,编译器同样会自动进行转换。
public static Integer show(Integer iParam){System.out.println("autoboxing example - method invocation i:" + iParam); | |
return iParam; | |
} | |
show(3); | |
int result = show(3); |
我们就以 Interger 类为例,下面看一段代码:
public class Main {public static void main(String[] args) {Integer i = 10; | |
int n = i; | |
} | |
} |
反编译 class 文件之后得到如下内容:
从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是 Integer 的 valueOf(int)方法。而在拆箱的时候自动调用的是 Integer 的 intValue 方法。
其他的也类似,比如 Double、Boolean,不相信的朋友可以自己手动尝试一下。
因此可以用一句话总结装箱和拆箱的实现过程:
装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过调用包装器的 xxxValue 方法实现的。(xxx 代表对应的基本数据类型)。
