tech-daily-questions
tech-daily-questions copied to clipboard
「小马哥每日一问」2019.08.12 期
问题描述
public class Hamlet {
public static void main(String[] args) {
Random rnd = new Random();
boolean toBe = rnd.nextBoolean();
Number result = (toBe || !toBe) ?
new Integer(3) : new Float(1);
System.out.println(result);
}
}
以上程序输出内容是?
(a) 运行时异常 (b) 3 (c) 1.0 (d) 以上答案都不是
请小伙伴们在评论区直接作答,谢谢~
注:请关注小马哥微信公众号【次灵均阁】,后续将有解答视频推送:
(b)
d 从小马哥出题的规律来看,肯定不是个正常的结果,越复杂的越有可能
3.0
3.0,判断语句始终为true啊。。。
3.0 涨姿势
(b)
首先,toBe or notToBe 的结果肯定是 true,所以结果肯定和 3 有关; 那么,凭什么是 Integer 或者 凭什么就是 Float 呢,水平有限,类型提升吧我猜,只能 javap 感受一下:
// new Integer(3)
21: new #5 // class java/lang/Integer
24: dup
25: iconst_3
26: invokespecial #6 // Method java/lang/Integer."
// new Float(1)
36: new #8 // class java/lang/Float
39: dup
40: fconst_1
41: invokespecial #9 // Method java/lang/Float."
// Float.valueOf(3) 47: invokestatic #11 // Method java/lang/Float.valueOf:(F)Ljava/lang/Float; 50: astore_3
所以,result.getClass() 的 结果是 java.lang.Float,程序输出是 3.0。
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html
@mercyblitz 稍做修改,还是那4个选项。:) Random rnd = new Random(); boolean toBe = rnd.nextBoolean(); Number a = new Integer(3); Number result = (toBe || !toBe) ? a : new Float(1); System.out.println(result);
改成 new Float(3) : new Integer(1),其他不变,字节码几乎一样
// new Float(3)
21: new #5 // class java/lang/Float
24: dup
25: ldc #6 // float 3.0f
27: invokespecial #7 // Method java/lang/Float."
// new Integer(1)
36: new #9 // class java/lang/Integer
39: dup
40: iconst_1
41: invokespecial #10 // Method java/lang/Integer."
// Float#valueOf 47: i2f 48: invokestatic #12 // Method java/lang/Float.valueOf:(F)Ljava/lang/Float;
class文件反编译后变成以下: public static void main(String[] args) { Random rnd = new Random(); boolean toBe = rnd.nextBoolean(); Number result = !toBe && toBe ? new Float(1.0F) : (float)new Integer(3); System.out.println(result); }
也就是说在执行的时候Integer强制转成了float,不清楚为什么会这样
d 三目运算符精度
@mercyblitz 我还想问一个问题, 为什么以下代码,在jdk1.8 及以上版本没问题,jdk1.7及以下版本编译报错?
Random rnd = new Random();
boolean toBe = rnd.nextBoolean();
List<String> result = (toBe || !toBe) ?
new ArrayList<String>() :
Collections.emptyList();
Why is the class called Hamlet?
Why is the class called Hamlet?
Because it's the magic :D
d 三目运算符精度
正解
涨知识了
自动类型转化啊 Number result = (toBe || !toBe) ? a : new Float(1); Integer跟Float在一起 result 类型往上自动提升 ,int 自动转化 long float double 反之强转丢失精度
三元运算符设计到一种双目运算符提升的特性 1.如果定义了数据类型的变量和未定义数据类型的变量参与双目运算符的后双目运算,那么返回的结果就是范围大(精度高)的类型。 2.如果两个定义了数据类型的变量参与双目运算符的后双目运算,那么返回的结果就是范围大(精度高)的类型。 3.如果直接进行数值的比较,则自动转型为范围大(精度高)的类型。