sitting.jpg
本文首发于公众号:javaadu
Java的类型系统由两部分组成:基本类型(primitive)和引用类型(reference type)。包装类指的是Java基础类型对应的引用类型。每个基本类型都有一个对应的包装类:
基本类型和包装类型有三个区别:
在Java中的泛型类不支持基本类型,只支持引用类型,因此,如果我们希望在泛型类中使用基本类型,就需要将基本类型先转换成引用类型。例如:Java集合框架只能存放引用类型的元素。
将基本类型转换成引用类型的方式有两种:构造方法、静态工厂方法。这里看一个将int值转换成Integer对象的例子,代码如下:
Integer object = new Integer(1);
Integer anotherObject = Integer.valueOf(1);
这两种转换方式对于int转Integer有区别:valueOf方法会优先返回缓存的数据([-128,127]),如果超出这个范围,才会使用构造方法创建包装类型。valueOf的代码如下:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
另外,如果需要从一个包装类型转换成基本类型,则需要使用相关的方法,例如:intValue()、doubleValue()等等:
int val = object.intValue();
在Java 1.5之前,开发者必须手动处理包装类型和基本类型之间的转换,例如要在一个集合中放入整数的时候,直接调用coll.add(5)
是不支持的。
Java 1.5增加了自动装箱(autoboxing)和自动拆箱(auto-unboxing)的特性,可自动完成包装类型和基本类型的转换。自动装箱指的是自动将一个基本类型转换成包装类型对象。
什么时候会发生自动装箱呢?
上述两种情况的例子代码如下:
List<Integer> list = new ArrayList<>();
list.add(1); //自动装箱
Integer val = 2; //自动装箱
自动装箱有助于提高代码的可读性。
不过在一些情况下,却不推荐自动装箱特性,例如:在循环中,下面的代码比预计的运行起来要慢一点:
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i; //sum被不断得自动拆箱和装箱
}
System.out.printfln(sum);
}
类型的转换是在等号左边和等号右边的变量数据类型不一致的时候发生,这时候需要将一个数字从一个数据类型转换成另一种数据类型。数据类型的转换可以分为隐式转换(自动类型转换)和显式转换(强制类型转换)两种。
隐式转换需要满足两个条件:
数据类型的级别规定如下(从左到右的转换顺序):
当两种类型的数据不兼容时,或者目标类型的取值范围小于源类型时,就无法进行隐式转换,这时候就需要进行显式转换(强制类型转换),例子代码如下:
int a = 3;
double b = 5.5;
a = (int)b;//显式转换,会丢精度