Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XTend null安全抛出NullPointerException_Nullpointerexception_Xtend - Fatal编程技术网

XTend null安全抛出NullPointerException

XTend null安全抛出NullPointerException,nullpointerexception,xtend,Nullpointerexception,Xtend,我正在将模板代码移植到XTend。在某个时候,我在测试用例中有这种类型的条件处理: @Test def xtendIfTest() { val obj = new FD if (true && obj?.property?.isNotNull) { return } fail("Not passed") } def boolean isNotNull(Object o) { return o != null } class

我正在将模板代码移植到XTend。在某个时候,我在测试用例中有这种类型的条件处理:

@Test
def xtendIfTest() {
    val obj = new FD
    if (true && obj?.property?.isNotNull) {
        return
    }
    fail("Not passed")
}

def boolean isNotNull(Object o) {
    return o != null
}
class FD {
 @Accessors
 String property
}
这与预期的一样,因为属性为null,测试将失败并显示“notpassed”消息。但是将isNotNull方法的返回类型简单更改为Boolean(包装器):

由于NullPointerException而失败。通过检查生成的java代码,我可以看到XTend使用了一个中间布尔对象表达式,这就是NPE的原因。我是否遗漏了XTend null safe运算符(?)的要点,或者我不能在运算符之后使用这样的方法


谢谢。

操作员行为正常。引发异常的原因是在if表达式中使用了布尔值,这需要自动取消装箱

如果您尝试以下操作:

@Test
def xtendIfTest() {
    val Boolean obj = null
    if (obj) {
        return
    }
    fail("Not passed")
}
您还将遇到NullPointerException

这与Java语言规范()一致-当需要自动取消装箱时,可能会产生NullPointerException:

@Test
public void test() {
    Boolean value = null;
    if (value) { // warning: Null pointer access: This expression of type Boolean is null but requires auto-unboxing
        // dead code
    }
}

希望有帮助。

简短回答:将第二个空安全呼叫更改为常规呼叫

即改变

obj?.property?.isNotNull
为此:

obj?.property.isNotNull
长答案:

下面将描述空安全运算符:

在许多情况下,如果 接收器为空

这意味着您的示例中的第二个调用,
property?
甚至不会调用
isNotNull
,如果调用的左侧是
null
。相反,它将返回
null
。因此,条件“有效”评估为:

if (true && null) {  // causes NPE when java tries to unbox the Boolean 
(顺便说一句,
true
在这种情况下是多余的,但我保留它只是为了防止您需要检查另一个条件-我假设您只是将其简化为
true
。)

如果您进行了我建议的更改,
obj?.property
将被计算,然后结果将被传递到
isNotNull
,计算结果如下:

if (true && isNotNull(null)) {
它返回正确的
布尔值
对象,该对象将按预期自动解除绑定

警告一句

在第一种形式的
isNotNull
中,即返回基元
布尔值
的形式,您实际上应该得到类似“基元值特征的Null安全调用isNotNull,将使用默认值false”的警告

这是因为您正在扩展空安全调用的意图,即如果操作符的左侧是
null
,则返回
null
,而不调用右侧方法。但是如果
isNotNull
返回一个基元
布尔值
,整个表达式显然不能计算为
null
,因此Xtend使用默认值,对于布尔值,它是
false

以另一种方式强调问题-它的计算结果为
false
,而不调用
isNotNull
-这意味着,即使在运算符之后使用方法
isNull
,它仍将返回
false

文档还提到了这种行为(尽管是一般性的):

对于基元类型,返回默认值(例如,int为0)。 在某些情况下,这可能不是您想要的,因此会发出警告 默认提出

因此,我建议始终在空安全调用的右侧使用非原语返回值。但是,如果您要像我建议的那样将
isNotNull
转换为常规调用,则此规则不适用,并且任何一种返回类型都可以

if (true && isNotNull(null)) {