Sonarlint 哨兵值假阳性

Posted

技术标签:

【中文标题】Sonarlint 哨兵值假阳性【英文标题】:Sonarlint sentinel value fake positive 【发布时间】:2022-01-23 11:32:29 【问题描述】:

我有下一个代码 sn-p,其中 sonarlint 工具说我的布尔变量 sentinel 总是评估为真,而 sentinel = true 这是一个无用的声明。

import static java.lang.System.*;

public class Sentinel 

    private static final int[] array = new int[]  0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;

    public static void main(String[] args) 
        boolean sentinel = false;
        int counter = 0;
        while (!sentinel) 
            out.println( "Counter: " + counter);
            out.println( "Array index: " + array[counter] );
            counter++;
            if ( counter == array.length - 1 ) 
                out.println( "End of the array reached" );
                sentinel = true;
                out.println( "Breaking..." );
                break;
            
        
    

sonarlint analisys 可能有什么问题?代码完美编译并按预期运行。

问候。

更新:

@kkk 提供了两个有价值的答案。见下文,但我把我更喜欢的放在这里:

import java.util.concurrent.atomic.AtomicBoolean;

import static java.lang.System.*;

public class Sentinel 

    private static final int[] array = new int[]  0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;

    public static void main(String[] args) 
        AtomicBoolean sentinel = new AtomicBoolean(false);
        int counter = 0;
        while ( !sentinel.get() ) 
            out.println( "Counter: " + counter);
            out.println( "Array index: " + array[counter] );
            counter++;
            if ( counter == array.length - 1 ) 
                out.println( "Counter limit reached" );
                sentinel.set( true );
                out.println( "Breaking..." );
                break;
            
        
    

【问题讨论】:

由于 break 语句导致循环退出,sentinel 在被读取之前就超出了范围。 那么sentinel 没有超出范围的时间呢?因为循环中断条件不正确?在我看来,这似乎是分析系统的一个很大的任意条件,并不反映现实 sentinel 是不必要的。拥有它并不会改变您的代码的功能。 【参考方案1】:

sentinel = true; 所做的更改从未被while (!sentinel) 看到。那是因为 break 语句。

话虽如此,您的代码使用for 循环要简单得多。你的while 只会让它变得复杂。

for(int counter = 0; counter < array.length; counter++) 
    out.println("Counter: " + counter);
    out.println("Array index: " + array[counter]);
    if (counter == array.length - 1) 
        out.println("End of the array reached");
        out.println("Breaking...");
    

或者,更好的是,在循环之后执行counter == array.length - 1 操作

for(int counter = 0; counter < array.length; counter++) 
    out.println("Counter: " + counter);
    out.println("Array index: " + array[counter]);

out.println("End of the array reached");
out.println("Breaking...");

【讨论】:

【参考方案2】:

将 sentinel 设为静态或用户 AtomicBoolean,这是可见性问题

【讨论】:

我不喜欢第一个,在太大的代码库上有一个静态类级别的成员可能会很糟糕,我希望将它放在方法中,所以 AtomicBoolean 工作得很好,而且删除 sonarlint analisys 错误。 不需要是staticAtomicBoolean。它说该值从未使用过的原因是,在设置它之后,该值从未使用过。 break 语句将您带出while 更简单的答案就是一起删除哨兵。 该代码 sn-p 它正在恢复另一段非常大的代码,其中需要有多个中断,但 sonarlint 抱怨在同一个 while 循环中没有多个中断语句,所以一个哨兵value 似乎是一个合适的选择。因此,将 break 替换为条件评估为 true 并检查 if 之后的值,如果 sentinel 不为 true,则在再次循环之后。

以上是关于Sonarlint 哨兵值假阳性的主要内容,如果未能解决你的问题,请参考以下文章

Redis哨兵模式(故障转移测试)

Redis中的哨兵模式

redis主从+哨兵

Redis 哨兵

Redis哨兵(Sentinel)机制 --高可用的保障

Redis-哨兵模式