java中的类型转化
今天看这张图,题目让我先查每种类型占多少位、能表示多大范围,再想结论。我自己边查边在 Java 里试了一遍,记一下。
先看位数:byte 八位、short 十六位、char 十六位但无符号(0 到 65535)、int 三十二位、long 六十四位、float 三十二位、double 六十四位。范围上 int 大约正负二十一亿,long 大约正负九百亿亿,float 最大能到三点四乘十的三十八次方,double 更大,能到一点八乘十的三百零八次方。
图里实线箭头是不用写任何东西就能自动走的转换,也就是从小到大往上走,安全;虚线箭头必须自己强转,而且转了真的会丢东西。我自己试了几个:(int)3.99 得到 3,它不是四舍五入,是直接把小数砍掉;(byte)200 变成 -56,(short)70000 变成 4464,(int)1e20 直接顶到最大值 2147483647。所以虚线那条路上的损失是实打实的。
但我觉得这张图最有意思的地方是第二层结论:不能光看位数。float 只有三十二位,排在小弟的位置,可 long → float、long → double 都是虚线。原因是浮点数把位数拆成了符号、阶码、尾数三部分,真正决定"能精确数到第几位"的是尾数:float 只有二十四位有效数字,double 五十三位,而 long 是六十四位精度,所以装不下。我拿 1234567890123456789 试了一下,转成 float 变成 1.234568E18,转成 double 也不等于原值;还有一个经典例子是 2 的 53 次方加 1,等于 9007199254740993,转成 double 就变成 ...992 了,最后那个 1 直接没了。结论就是:只要方向指向 float 或 double,就一定是有损的,别看 double 的范围比 long 大得多。
char 那个位置也挺关键:它是十六位无符号,比 short 还"大"一点,所以 char → int 是实线,(int)'A' 就是 65,反过来 int → char 就得自己强转。浮点之间只有 float → double 是实线,因为 double 的范围和有效数字都比 float 大,能完整装下 float。
还有一个连带的坑我也顺手试了:byte、short、char 一参与运算就会先提升成 int,所以 byte b = 1; b = b + 1; 是编译不过的,javac 报"不兼容的类型: 从int转换到byte可能会有损失",得写成 b = (byte)(b + 1);。有意思的是 b++ 却能过,因为它内部偷偷帮你做了强转。
总的就一句话:实线放心走,虚线自己负责任;而且判断有没有损失,看的是"有效数字够不够",不是"总位数谁多"。
浙公网安备 33010602011771号