java - 布尔值,条件运算符和自动装箱

为什么抛出false

public static void main(String[] args) throws Exception {

Boolean b = true ? returnsNull() : false; // NPE on this line.

System.out.println(b);

}

public static Boolean returnsNull() {

return null;

}

虽然这不是

public static void main(String[] args) throws Exception {

Boolean b = true ? null : false;

System.out.println(b); // null

}

顺便提一下,该解决方案是通过2377135880046604321替换false,以避免null被拆箱至boolean - 这是不可能的。 但这不是问题。 问题是为什么? JLS中是否有任何引用证实了这种行为,尤其是第二种情况?

4个解决方案

89 votes

不同之处在于Boolean方法的显式类型会影响编译时表达式的静态类型:

E1: `true ? returnsNull() : false` - boolean (auto-unboxing 2nd operand to boolean)

E2: `true ? null : false` - Boolean (autoboxing of 3rd operand to Boolean)

请参阅Java语言规范,第15.25节“条件运算符”?:

对于E1,第2和第3个操作数的类型分别为Boolean和Boolean,因此本节适用于:

如果第二个和第三个操作数之一是boolean类型,另一个类型是Boolean类型,那么条件表达式的类型是boolean。

由于表达式的类型是Boolean,因此必须将第二个操作数强制转换为Boolean.编译器将自动取消装箱代码插入第二个操作数(返回值false),使其类型为E1.这当然会导致来自null的NPE 在运行时返回。

对于E2,第2和第3个操作数的类型分别为Boolean(不是像E1中的Boolean)和false,因此不适用特定的输入条款(请阅读'em!),因此最终的“其他”条款适用:

否则,第二和第三操作数分别是S1和S2类型。 设T1是将拳击转换应用于S1所产生的类型,让T2为应用到S2的装箱转换所产生的类型。 条件表达式的类型是将捕获转换(第5.1.10节)应用于lub(T1,T2)(第15.12.2.7节)的结果。

S1 == Boolean(见§4.1)

S2 == Boolean

T1 == box(S1)== Boolean(参见§5.1.7中的拳击转换列表中的最后一项)

T2 ==方框(S2)==`布尔值

lub(T1,T2)== Boolean

因此条件表达式的类型为Boolean,第3个操作数必须强制转换为Boolean.编译器为第3个操作数(false)插入自动装箱代码。 第二个操作数不需要E1中的自动拆箱,因此返回null时不会自动取消装箱NPE。

这个问题需要类似的类型分析:

Java条件运算符?:结果类型

Bert F answered 2019-06-04T05:30:03Z

22 votes

这条线:

Boolean b = true ? returnsNull() : false;

内部转变为:

Boolean b = true ? returnsNull().getBoolean() : false;

执行拆箱; 因此:null.getBoolean()将产生NPE

这是使用自动装箱时的主要缺陷之一。 这种行为确实记录在5.1.8 JLS中

编辑:我认为拆箱是由于第三个运算符是布尔类型,如(隐式强制转换):

Boolean b = (Boolean) true ? true : false;

jjungnickel answered 2019-06-04T05:30:59Z

16 votes

从Java语言规范,第15.25节:

如果是第二个和第三个之一   操作数的类型为boolean和   另一种类型是布尔型,   那么条件的类型   表达式是布尔值。

因此,第一个示例尝试调用Boolean.booleanValue(),以便根据第一个规则将Boolean转换为boolean。

在第二种情况下,第一个操作数是null类型,当第二个操作数不是引用类型时,应用自动装箱转换:

否则,第二和第三   操作数是S1和S2类型   分别。 设T1是那种类型   应用拳击的结果   转换为S1,让T2成为   应用拳击造成的类型   转换为S2。 的类型   条件表达式就是结果   应用捕获转换   (§5.1.10)至lub(T1,T2)(§15.12.2.7)。

axtavt answered 2019-06-04T05:31:59Z

0 votes

我们可以从字节代码中看到这个问题。 在main的字节码的第3行,3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z,值为null的装箱布尔值,invokevirtual方法java.lang.Boolean.booleanValue,它当然会抛出NPE。

public static void main(java.lang.String[]) throws java.lang.Exception;

descriptor: ([Ljava/lang/String;)V

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=2, args_size=1

0: invokestatic #2 // Method returnsNull:()Ljava/lang/Boolean;

3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z

6: invokestatic #4 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;

9: astore_1

10: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;

13: aload_1

14: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V

17: return

LineNumberTable:

line 3: 0

line 4: 10

line 5: 17

Exceptions:

throws java.lang.Exception

public static java.lang.Boolean returnsNull();

descriptor: ()Ljava/lang/Boolean;

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=0, args_size=0

0: aconst_null

1: areturn

LineNumberTable:

line 8: 0

Yanhui Zhou answered 2019-06-04T05:32:31Z

java 布尔表达式_java - 布尔值,条件运算符和自动装箱相关推荐

  1. java随机布尔值_Java 布尔值(Boolean)

    1.Java 布尔值 通常,在编程中,将需要一个只能具有两个值之一的数据类型,表示逻辑判断条件的真假. 为此,Java具有boolean数据类型,该数据类型可以是值true或false. 2.bool ...

  2. java中怎么定义true或false_为什么Java中的布尔值只接受true或false? 为什么也不要1或0?...

    有什么理由为什么Java布尔值仅采用true或false为什么不采用1或0? 这不是一个复杂的问题,但是我也没有理由反对. 您忘记了FILE_NOT_FOUND 因为它是强类型的 在Java中,只能使 ...

  3. java返回一个布尔值_关于java:返回布尔值的方法

    好的,所以我的问题是关于布尔值的回报. 对于我的Comp Sci作业,我必须使用方法制作课程注册程序,其中之一是添加课程方法. 基本上,您在目录中搜索该班级,如果匹配,则将其添加到学生时间表中,并返回 ...

  4. java 布尔表达式_Java中的布尔表达式优化

    考虑Java中的以下方法: public static boolean expensiveComputation() { for (int i = 0; i < Integer.MAX_VALU ...

  5. 第三次学JAVA再学不好就吃翔(part64)--自动装箱和自动拆箱

    学习笔记,仅供参考 自动装箱和自动拆箱 装箱:把基本类型转换为包装类类型 int x = 100; Integer i1 = new Integer(x); 拆箱:把包装类类型转换为基本类型 int ...

  6. oracle 布尔转换java布尔_java 布尔值一种赋值方法

    解决在配置Oracle数据库连接错误问题 项目开发使用的Oracle,但是使用了不同的版本的Oracle数据库.然后自己在电脑上安装了2个连接客户端,版本分别是: 10.2.0 12.1.0 用Toa ...

  7. c# java 语法_Java与C#的语法区别

    1.作用域 在java中 { { int a=1; } int a=2;//以上a作用域外的以下,再声明同名的变量,是允许的: } 在C#中,以上是不允许的[只要在同一个作用域内,以上或以下的代码中 ...

  8. java 自动装箱自动拆箱

    1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...

  9. java 类库_Java基础类库

    面向对象的核心-类和对象 类的语法定义 类的修饰符 static可以修饰变量和方法,称为类变量.类方法,它们属于类本身.不被static修饰的变量和方法称为实例变量.实例方法,属于类的实例. 在类准备 ...

最新文章

  1. 软件开发经验总结(五)读源代码的艺术
  2. 北京内推 | 地平线视觉算法团队招聘视觉算法实习生
  3. 在WPF程序中打开网页:使用代理服务器并可进行JS交互
  4. 自动化测试用例设计原则
  5. core和node开发小程序_node+微信小程序实现商城案例
  6. 融云通讯服务器,vue使用融云即时通讯,老是报了发送失败,服务器超时
  7. python列表嵌套元组拆分,将包含整数和字符串的列表转换为嵌套元组Python
  8. xml模块、项目开发过程
  9. 05 | 服务编排层:Pipeline 如何协调各类 Handler ?
  10. JAX-RPC学习笔记(1)-Hello World!
  11. 【阿里云IoT YF3300】6.物联网设备报警配置
  12. 韦福怎么编译c 语言,c语言第1章 绪论.ppt
  13. Activiti7工作流引擎介绍
  14. 如何解决“数据错误,循环冗余检查”
  15. 欧普LED灯维修记录及原理解密
  16. 【NOIP2018模拟赛2018.8.28】video
  17. 【WEB】前端系统配色方案(全览)
  18. boundschecher2
  19. 基于DCT变换图像去噪算法的进一步优化(100W像素30ms)
  20. 网络空间技能大赛A模块(乱)

热门文章

  1. HALCON示例程序measure_chip.hdev芯片封装检测
  2. java class 关键字_java关键字及其作用
  3. 驻定相位原理(POSP)的简单应用
  4. centos 安装 MatConvNet (gpu)
  5. 如何让Latex公式字体变小
  6. mysql查询的时候会涉及到锁_Mysql 查询 锁的问题?
  7. 获取当前日期0点及23点59的时间戳
  8. spring指导的index.html在spring文件夹中的位置
  9. MYSQL:基础——触发器
  10. 求数组中的最小子数组,时间复杂度o(n),java