在构造函数中创建 Random 时摆脱 FindBugs "Random object created and used only once"

Getting rid of FindBugs "Random object created and used only once" when Random is created in the constructor

我想摆脱 FindBugs 警告 "DMI: Random object created and used only once"。在下面的示例中,随机数仅在对象构造时生成一次。换句话说,对于 class Wrap 的单个实例的生命周期,不会创建 java.util.Random 的其他实例。有没有办法摆脱这个警告(除了添加注释),特别是在构造函数中实例化 java.util.Random 的情况下?

public final class Wrap {

    /**
     * Random generated double.
     */
    private final double random;

    /**
     * Constructor.
     */
    public Wrap() {
        this.random = new Random().nextDouble();
    }

    public Double value() {
        return this.random;
    }

}

您不应该在每次实例化 class 时都创建 Random 的新实例。这就是 FindBugs 警告告诉您的内容。 The full warning is(强调我的):

This code creates a java.util.Random object, uses it to generate one random number, and then discards the Random object. This produces mediocre quality random numbers and is inefficient. If possible, rewrite the code so that the Random object is created once and saved, and each time a new random number is required invoke a method on the existing Random object to obtain it.

If it is important that the generated Random numbers not be guessable, you must not create a new Random for each random number; the values are too easily guessable. You should strongly consider using a java.security.SecureRandom instead (and avoid allocating a new SecureRandom for each random number needed).

要避免警告,有几种可能:

  • 在您的 class

    中创建常量 Random
    private static final Random RANDOM = new Random();
    

    你在构造函数中重用

    this.random = RANDOM.nextDouble();
    

    这样,不会创建新实例。

  • 使用 Math.random() 因为您实际上想要一个介于 0 和 1 之间的随机双精度值。
  • 使用 ThreadLocalRandom class 和

    this.random = ThreadLocalRandom.current().nextDouble(1);
    

    这也将 return 在 0 和 1(不包括)之间随机加倍。