当前位置: 首页 > 面试题库 >

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

尹弘壮
2023-03-14
问题内容

为什么会抛出 NullPointerException

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
}

解决方案是通过替换false方式Boolean.FALSE来避免null被取消装箱-这boolean是不可能的。但这不是问题。问题是为什么?JLS中是否有任何引用可以证实这种行为,尤其是第二种情况?


问题答案:

别在于方法的显式类型returnsNull()会在编译时影响表达式的静态类型:

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节“ 条件运算符?”。:

  1. 对于E1,第二和第三操作数的类型分别为Booleanboolean,因此该子句适用:

如果第二个操作数和第三个操作数之一为布尔型,而另一个的类型为布尔型,则条件表达式的类型为布尔型。

由于表达式的类型为boolean,因此第二个操作数必须强制为boolean。编译器将自动拆箱代码插入第二个操作数(返回值returnsNull())以使其为type boolean。这当然会导致null在运行时从返回的NPE 。

  • 对于E2,第二和第三操作数的类型分别为<special null type>(不同于BooleanE1!)boolean,因此没有特定的键入子句适用(请去读’em!),因此最后的“否则”子句适用:

否则,第二和第三操作数分别为S1和S2类型。令T1为对S1进行装箱转换所产生的类型,而T2为对S2进行装箱转换所产生的类型。条件表达式的类型是将捕获转换(§5.1.10)应用于lub(T1,T2)(§15.12.2.7)的结果。

  • S1 == <special null type>
  • S2 == boolean
  • T1 == box(S1)== <special null type>
  • T2 == box(S2)==Boolean
  • lub(T1,T2)== Boolean
    因此,条件表达式的类型为,Boolean并且第三个操作数必须强制为Boolean。编译器为第三个操作数(false)插入自动装箱代码。第二个操作数不需要像中一样的自动拆箱E1,因此null返回时没有自动拆箱的NPE 。


 类似资料:
  • 概述 布尔运算符用于将表达式转为布尔值,一共包含四个运算符。 取反运算符:! 且运算符:&& 或运算符:|| 三元运算符:?: 取反运算符(!) 取反运算符是一个感叹号,用于将布尔值变为相反值,即true变成false,false变成true。 !true // false !false // true 对于非布尔值,取反运算符会将其转为布尔值。可以这样记忆,以下六个值取反后为true,其他值都

  • --编辑 再考虑一下,我怀疑NPE来自返回null的rsrqs.get(),我认为java试图在装箱返回整数之前将其解框为int。integer.valueOf()强制Java执行unbox-box步骤。故事的寓意;不要只是忽略Eclipse中的那些拳击警告;)

  • Java 提供了一个特别的三元运算符(也叫三目运算符)经常用于取代某个类型的 if-then-else 语句。 条件运算符的符号表示为“?:”,使用该运算符时需要有三个操作数,因此称其为三目运算符。使用条件运算符的一般语法结构为: 其中,expression 是一个布尔表达式。当 expression 为真时,执行 statement1, 否则就执行 statement3。此三元运算符要求返回一个

  • 问题内容: 我知道for的规则,但是是什么?请举例说明。 问题答案: 这些是按位与和按位或运算符。 感谢卡洛斯指出在Java语言规范中相应的部分(15.22.1,15.22.2关于基于其输入操作者的不同的行为)。 的确,当两个输入均为布尔值时,这些运算符被视为布尔逻辑运算符,并且其行为类似于和运算符,但它们不会短路,因此以下操作是安全的: 这不是: “短路”是指操作员不必检查所有条件。在上述示例中

  • 我有一个简单的类,在下面编译时,它会正确地自动装箱整数,但是,对于我的布尔值,它无法这样做,它坚持我应该将参数更改为布尔值。我使用的是JDK1.8,否则编译器会抱怨整数转换。我看不出我做错了什么?所有包装器类都可以开箱即用,或者我是这么想的? 自动装箱不是一个双向过程吗?