跳到主要内容

7.1 数据类型转换

在实际开发过程中,有时需要将不同数据类型的值进行转换,这个过程称为数据类型转换。

由于每种数据类型所占用的内存空间大小不同,所以在类型转换时需要注意一些问题。

自动类型转换(隐式类型转换)

自动类型转换发生在占内存小的类型往大内存类型转换时,就好比把一个小箱子放到一个大箱子中,这个转换过程是自动的、隐式的。

public static void main(String[] args) {
int a = 100;
// 将int类型变量a赋值给long类型变量b,自动转换
long b = a;
}

提示

byte -> short -> int -> long,这个过程是自动类型转换。

字面值常量

字面值常量包括整数字面值、浮点数字面值、字符型字面值、布尔型字面值、字符串字面值,例如:101.0'A'true"Hello",这些直接的值都是字面值,字面值具有不可变性。

整型字面值默认类型

在基本数据类型中,Java会把整数字面值默认为int类型,会把浮点数字面值默认为double类型。

public static void main(String[] args) {
// Java会认为这个字面值100是int类型
byte a = 100;
}

那么,byte a = 100; 为什么int类型的整数,可以直接赋值给byte呢?

原因在于,在编译阶段,Java编译器发现整数字面值100在byte类型的取值范围内,所以,可以直接将100赋值给byte类型变量a。

提示

对于这种处理,Java语言规范中是这么解释的:如果=的右边是常量表达式,而且类型是byte、short、char或int,那么Java在必要时会自动执行narrowing conversion,只要这个常量表达式的值在=左边变量的取值范围之内。

if the expression is a constant expression of type byte, short, char, or int: A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

如果将整数字面值128赋值给变量a,编译器会直接报错。因为128超过了byte的存储范围,编译器会提示它变量a是byte类型,而你提供的是int类型。

如果将一个值在byte取值范围内int类型变量赋值byte类型变量,这种情况下同样也会编译报错。因为在编译阶段无法得知变量a的值是多少,所以将int类型变量赋值给byte类型会报错。


整数字面值还有这样一种情况,因为整数字面值默认是int类型,这个字面值明显已经超过的int类型的长度,所以,编译器会提示这个整数太大了。

这里需要在整数后面加上一个L或者l来告诉Java编译器,这个字面值是long类型的。

通过上面的介绍,看下面这几行代码,能理解吗?

byte a = 50; // ok
byte b = 60; // ok
byte c = a + b; // error
byte d = 10 + 20; // ok
byte e = 127 + 5; // error

关于浮点数字面值,Java会默认浮点数字面值是double类型,如果是float字面值,需要在浮点数值后面加上 F或者f

强制类型转换(显式类型转换)

强制类型转换发生在大转小的过程中,这种情况下需要显式地指定要转换的数据类型。强制类型转换可能会发生精度丢失,就好比把大箱子放到小箱子中,大箱子肯定要变形。

public static void main(String[] args) {
int a = 100;
byte b = (byte) a;
}

int类型变量a的值是100,在byte类型取值范围内,所以强转后不会发生精度丢失。

但如果变量a超过的byte的取值范围,就会发生精度丢失,像下面的代码一样。

public static void main(String[] args) {
int a = 128;
byte b = (byte) a; // -128
}