SonarLint:在此处使用原始布尔表达式

27

我有以下的Properties类:

class Properties {
    private Boolean enabled;

    public Boolean getEnabled() {
        return enabled;
    }
}

如果我编写以下代码,则SonarLint会在if条件上发出警告,指出“在此处使用原始布尔表达式。”

if (!properties.getEnabled()) {
    return true;
}
// more code

将if条件更改为以下内容可以消除警告。但是那样不够可读,SonarLint不可能想要那样吧?


Changing the if condition to the following eliminates the warning. However, it becomes less readable. Is that really what SonarLint intends?
if (properties.getEnabled().equals(Boolean.FALSE)) {
    return true;
}
// more code

SonarLint究竟希望我在这里做什么?问题是什么?


4
“enabled”为null意味着什么? - Andy Turner
2
也许将您的“enabled”属性声明为原始布尔值会更好。我认为Sonarlint试图防止空指针异常。 - D. Lawrence
2
@D.Lawrence确实,在它之前加上一个空值检查会消除警告。这是一个有用的警告,但是信息非常令人困惑。谢谢。 - findusl
1
@AndyTurner不错的图片。它应该不为null,因为它也被注释为NotNull。但是由于设置值的框架,它是非原始类型。是的,有人可能会说这个框架不太好,而且他们可能是正确的。但并不是我的选择。通过Lawrence的提示,SonarLint也接受了它。谢谢你的尝试和快速回复。 - findusl
5个回答

38

正如其他人已经提到的,Sonar希望您确保没有任何空指针异常,或者至少在尝试验证变量之前进行空检查,这就是我在执行空检查之后尝试进行验证时所看到的:

如果我有下面的代码,Sonar会发出警报,表示此代码可能引发空指针异常。

if (properties.getEnabled()) {
       // Your code
}

但是,如果我添加了一个快速的空值验证,Sonar就不会再抱怨了:

if (properties.getEnabled() != null && properties.getEnabled()) {
       // Your code
}

现在,正如您所提到的,您可以使用Boolean类来比较布尔值,代码如下:

Boolean.TRUE.equals(properties.getEnabled());

你可以像下面的代码一样将它放在 if 语句中:

if (Boolean.TRUE.equals(properties.getEnabled())){
       // Your code
}

这可能看起来有点啰嗦,但 Boolean.TRUE.equals() 的实现会检查对象是否为 Boolean 类的实例,而 null 无法是任何类的实例,因为 null 不是实例。您可以在此处找到更好的解释:Is null check needed before calling instanceof?

它们曾经有一个非常好而简单的测试集,用于理解什么被接受,什么不被接受,我在我的第一篇回答中发布了它,但看起来它在主干版本中已经不存在了(我仍然添加它以便更容易理解,但这是旧版 Sonar,只能作为参考使用):https://github.com/SonarSource/sonar-java/blob/5.14.0.18788/java-checks/src/test/files/checks/BoxedBooleanExpressionsCheck.java

您还可以引用此规则的实现代码:https://github.com/SonarSource/sonar-java/blob/master/java-checks/src/main/java/org/sonar/java/checks/BoxedBooleanExpressionsCheck.java#L131


有趣的是,Sonar会接受你声明的空值检查,因为getter只是一个函数,可以在每次调用时返回不同的值。 - findusl
我不明白为什么Sonar不允许我这样做,这就是你想要验证getter不返回null的原因,因为在每种情况下,你的对象可能包含true/false/null,只有在运行时才能知道值。 - Damonio
但你没有澄清它。第一次调用getEnabled可能返回与第二次调用不同的结果。为了在这里保险起见,您需要将结果保存到本地变量中,然后使用该变量进行操作。 - findusl
我明白即使你将结果保存到本地变量中,它可能会有所不同,但你只会存储对布尔值的引用,而不是实际值,如果另一个线程使用相同的对象,则该值可能会更改。 可能的原因是该对象在函数范围内而不是成员变量中,因此对于Sonar来说,可以保证没有其他线程会修改该对象。 但是,如果存在线程不安全性,那么像你提到的将实际值存储在本地变量中是最好的选择。 - Damonio

1
使用org.apache.commons.lang3.BooleanUtils,它是一种空值安全的方式:
if (BooleanUtils.isNotTrue(properties.getEnabled())) {
    return true;
}

3
你不需要任何库,只需使用这个 Boolean.TRUE.equals(properties.getEnabled());,而且它是空值安全的。 - Snigdhajyoti

0

这似乎有一个简单的答案。如果该属性是可空的,那么 getter 函数的健壮性应该有所帮助。

class Properties {
    private Boolean enabled;

    public Boolean isEnabled() {
        return enabled == true;
    }
}

-1

尝试使用.booleanValue()方法,像这样:

if(properties.getEnabled().booleanValue()) {
}

希望能对您有所帮助。


如果properties.getEnabled()返回空,则会抛出空指针异常。 - Snigdhajyoti
确实存在异常的可能性,对我来说,IntelliJ抱怨“不必要的解包 'properties.getEnabled().booleanValue()'”,所以编辑器中仍然存在明显的问题。 - gluttony

-3

试试这个:

public boolean x (){ 
    boolean prop=properties.getEnabled() 
    if (prop) { 
        return true; 
    }else return false; 
}

1
如果 properties.getEnabled() 返回空值,它将抛出空指针异常。 - Snigdhajyoti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接