1 Cbdy 2020-03-22 08:24:04 +08:00 via Android 因为这两行调用的是两个不同的 println,和 Java 方法的重载机制有关 |
![]() | 3 hanshijun 2020-03-22 08:35:53 +08:00 三目运算符会进行自动类型上升 |
![]() | 4 aneureka 2020-03-22 08:37:33 +08:00 via iPhone 因为你这个三元表达式返回的是 float,就算你返回的值是 int 也会被类型转换为 float |
![]() | 5 xuanbg 2020-03-22 08:54:25 +08:00 三元表达式的结果必须是同一个类型。在这里 integer 被隐式转换成 float 了。 |
6 humpy 2020-03-22 09:03:19 +08:00 ![]() 两个操作数分别是 Integer 类型和 Float 类型,根据 [jls-15.25.2]( https://docs.oracle.com/javase/specs/jls/se14/html/jls-15.html#jls-15.25.2 ),条件表达式的结果类型是两个操作数类型提升后的类型: 「 Otherwise, general numeric promotion (§5.6) is applied to the second and third operands, and the type of the conditional expression is the promoted type of the second and third operands.」 根据 [jls-5.6]( https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html#jls-5.6 ) 描述的类型提升规则: 1. 两个操作数拆包; 2. 拆包后,一个操作数是 int,一个是 float,将 int 扩展为 float 「 1. If any expression is of a reference type, it is subjected to unboxing conversion ( §5.1.8 ). 2. Next, widening primitive conversion ( §5.1.2 ) and narrowing primitive conversion ( §5.1.3 ) are applied to some expressions, according to the following rules: If any expression is of type double, then the promoted type is double, and other expressios that are not of type double undergo widening primitive conversion to double. Otherwise, if any expression is of type float, then the promoted type is float, and other expressions that are not of type float undergo widening primitive conversion to float. 」 因此这个语句最终的结果是 float 。 --- 可以写一段简单的代码看一下这个过程: cat a.java class a { public static void main(String[] args) { System.out.println(true ? Integer.valueOf(1) : Float.valueOf(3)); } } 查看它编译后的字节码,可以看到「 10: i2f 」这行确实做了 int -> float 的类型提升: javap -v a.class ... public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: iconst_1 4: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 7: invokevirtual #4 // Method java/lang/Integer.intValue:()I 10: i2f 11: invokevirtual #5 // Method java/io/PrintStream.println:(F)V 14: return |
![]() | 8 geelaw 2020-03-22 09:30:33 +08:00 ![]() @humpy #6 感谢查阅文档,值得注意的是这里的类型转换会尝试 unbox,导致 cond ? a : b 里面若 a 、b 具有原始类型的引用版本且其中一个是 null,则可能导致意外的空引用异常,这个可以加入 Java 反人类设计之一了。 public class HelloWorld { public static void main(String[] args) { System.out.println((Integer)null); System.out.println((Object)(Integer)null); System.out.println((Float)null); System.out.println((Object)(Float)null); System.out.println(true ? (Object)(Integer)null : Float.valueOf(1.0f)); System.out.println(true ? (Integer)null : (Object)Float.valueOf(1.0f)); // 下面这行会抛出异常 System.out.println(true ? (Integer)null : Float.valueOf(1.0f)); } } 相应的,在 C# 里则无此问题大多数情况下无法产生声明类型是值类型但被当作引用类型的表达式。最接近的两个情况: 可空类型的转换是正常的(这点比 Java 自然很多),表达式 true ? (int?)null : (float?)1.0f 等同于 (float?)null 。 值为装箱后的值类型的引用类型转换是正常的(这点同 Java ),表达式 true ? (IConvertible)(int?)null : (float?)1.0f 等同于 (object)null 。 |
9 hhhsuan 2020-03-22 11:38:33 +08:00 又学会一种回字的写法 |
![]() | 10 ae86 2020-03-22 12:19:16 +08:00 路过,跟着楼主一起学习 ![]() |
11 yeqizhang 2020-03-22 14:18:21 +08:00 via Android 这种问题没遇到还真不知道,网上教程也没看到提到过。之前有网上做面试题,有一道题就是这个,我做错了,这面试题真偏…… |
13 zxCoder 2020-03-22 18:59:38 +08:00 学习了 |
![]() | 15 banmuyutian 2020-03-22 20:12:05 +08:00 学习了 |
16 jiom 2020-03-22 22:52:36 +08:00 学习了 |
17 757384557 2020-03-23 09:04:59 +08:00 第一次看到这种问题,学习了 |
![]() | 18 niu0619 2020-03-23 09:55:56 +08:00 学习了 |
![]() | 19 yuanshuai1995 2020-03-23 11:02:48 +08:00 学写了 |
20 yibinhp 2020-03-23 11:19:07 +08:00 学写了 |
![]() | 21 wozhizui 2020-03-23 11:52:09 +08:00 学习了, |
![]() | 22 pengjl 2020-03-23 14:20:03 +08:00 学习了 |
![]() | 23 sunziren 2020-03-23 16:30:02 +08:00 学到老,活到老 |
![]() | 24 sunziren 2020-03-23 16:30:16 +08:00 学到老,活到老,学习了 |
![]() | 25 rancc 2020-03-23 17:04:32 +08:00 学习了 |
26 gotonull 2020-03-23 17:30:36 +08:00 学习了 |
![]() | 27 zhiguang 2020-03-23 17:52:11 +08:00 又能 zb 了 |