类型转换是什么意思
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。