Skip to content

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

I want to get rid of the FindBugs warning “DMI: Random object created and used only once”. In the following example, the random number is generated only once upon the object construction. In other terms, for the lifecycle of a single instance of the class Wrap, no other instances of java.util.Random will be created. Is there a way to get rid of this warning (other than adding an annotation), specifically in the case where java.util.Random is instantiated in the constructor ?

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;
    }

}

Answer

You should not create new instances of Random every-time your class is instantiated. This is what the FindBugs warning is telling you. The full warning is (emphasis mine):

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).

To avoid the warning, there are several possibilies:

  • create a constant Random in your class

    private static final Random RANDOM = new Random();
    

    that you reuse inside the constructor with

    this.random = RANDOM.nextDouble();
    

    This way, no new instances are created.

  • Use Math.random() since you effectively want a random double between 0 and 1.
  • Use the ThreadLocalRandom class with

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

    that will also return random double between 0 and 1 (exclusive).