Menu

Java 类型转换:自动转换、强制转换与互转

Java 如何在类型之间转换:自动的拓宽转换、显式的窄化强制转换、窄化时会丢失哪些数据,以及数字和字符串之间的转换。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

类型转换是什么意思

Java 是静态类型语言:每个值都有类型,编译器不会让你悄悄混用不兼容的类型。类型转换就是把一个值从一种类型转换成另一种类型的方法:有时 Java 会替你完成,有时你必须显式地要求它。

转换有两个方向。从较小的类型转到较大的类型(把 int 放进 double)是安全的,会自动发生。从较大的类型转到较小的类型(把 double 放进 int)可能丢失数据,所以 Java 要求你用强制转换明确写出来。

拓宽:自动转换

拓宽转换把一个值放进容量更大的类型。这不会丢失任何东西,所以 Java 会自动完成,不需要强制转换:

int 类型的 7 放进 double 后变成了 7.0。数字的拓宽顺序是 byte -> short -> int -> long -> float -> double;沿着这条链从左往右赋值,永远不需要强制转换。这也是为什么在算术运算中混用类型通常“直接就能用”:Java 会先把较小的操作数拓宽。

窄化:显式强制转换

反过来的方向,也就是窄化转换,可能会丢失数据,所以除非你在值前面用括号写上目标类型,否则编译器会拒绝:

(int) pi 就是强制转换。注意它做了什么:它会向零截断,直接丢掉小数部分。3.9 变成 3,-3.9 变成 -3。它不会四舍五入。如果你想要四舍五入,得换一个工具:

忘记强制转换会截断,是新手最常见的 bug 之一:如果你“四舍五入”后的数字总是少 1,原因通常就在这里。

整数除法的陷阱

这个坑几乎每个人都会踩一次。当两个操作数都是 int 时,/ 运算符做的是整数除法,余数会被丢掉,而且这发生在赋值给 double 之前:

a / b 就是 7 / 2,完全按 int 运算,结果是 3。之后再拓宽成 double,只是把 3 变成 3.0,.5 早就没了。先把其中一个操作数强制转换成 double((double) a / b),整个表达式就会按浮点数计算,得到你想要的 3.5。只需要转换一边,Java 会把另一边拓宽来匹配。

窄化时的溢出

强制转换不会检查值是否放得下。放不下时,多出的位会被直接截掉,你会得到一个出人意料的结果,没有错误,也没有警告:

300 放不进 byte,高位被丢弃,你得到的是 44。这是“无声”的数据丢失:程序运行正常,却给出了错误的答案。只有在确定值能放进较小的类型时,才做窄化转换。

数字与字符串的互相转换

String 是对象,不是数字,所以你不能用 (int) 强制转换它,那会导致编译错误。转换要用专门的方法:

从文本转成数字用 Integer.parseInt / Double.parseDouble。如果字符串不是合法的数字(比如 "hello"),这些方法会抛出 NumberFormatException。从数字转成文本,用 String.valueOf(n),或者直接和 "" 拼接,因为 n + "" 会把 int 强制变成 String。注意 "5" + 1(得到字符串 "51")和 5 + 1(得到 6)的区别:只要有 String 参与,+ 就表示拼接。

对象的强制转换

强制转换不只适用于基本类型,也适用于对象引用。你可以沿着继承链把引用转换成相关的类型:拓宽到父类型是自动的,再窄化回来则需要显式强制转换,而且只有当对象确实是那个类型时才安全:

Object o = "hello";
String s = (String) o;        // OK: o actually refers to a String
Integer bad = (Integer) o;    // compiles, but throws ClassCastException at runtime

第二次强制转换可以通过编译,但运行时会抛出 ClassCastException 而崩溃,因为这个对象是 String,不是 Integer。等你学到继承和多态时会正式接触到这一点;现在只要知道,(Type) 语法在对象上也是同样的思路。

常见问题

Java 中的类型转换是什么?

类型转换就是把一个值从一种数据类型转换成另一种。Java 会自动完成小范围的“拓宽”转换(比如 int 转 double),但可能丢失数据的“窄化”转换(比如 double 转 int)必须显式强制转换:int n = (int) 3.9;。

Java 中如何把 double 转成 int?

在值前面用括号写上目标类型:int n = (int) 3.9;。这会向零截断(丢掉小数部分),所以结果是 3,而不是 4。如果想四舍五入,就用 Math.round(3.9),它返回 4。

Java 中如何把 String 转成 int?

String 不是数字,所以不能用 (int) 强制转换。用 Integer.parseInt("42") 得到 int,或用 Double.parseDouble("3.14") 得到 double。如果文本不是合法的数字,这些方法会抛出 NumberFormatException。

Coddy 编程语言插图

和 Coddy 一起学编程

开始