Java SecureRandom 声明应该是静态的 class 特定的或者可以是特定于实例的

Java SecureRandom declaration should be static class specific or can be instance specific

我正在尝试使用 SecureRandom 在我的 java 项目中生成随机数。但是我对如何为 SecureRandom 保留我的对象有点困惑。应该是 static class 成员。我不打算从外面打电话。下面是我当前的实现:

Class MyClass {

    private static final SecureRandom secureRandom = new SecureRandom();

    private long calculate(int noOfRetry){
        final long value = someValueCalculationWith-noOfRetry;
        final float randomNo = secureRandom().nextFloat() + 1;
        return (long) (value*randomNo);
    }
}

这是在 java 中使用 SecureRandom 的正确方法吗?

不,不要成功 static。如果您愿意,可以将其设为实例字段,但将其设为 class 字段并不是最佳选择。例如。请参阅 Random class 上关于线程安全的说明,它源自:

Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs.

请注意 ThreadLocalRandom 不是 加密安全的,因此对您来说不是一个好的选择。一般来说,你应该尽量避免使用 static class 字段,尤其是 当实例是 stateful.

如果您只需要在一个或几个不在紧密循环中的方法中使用随机实例,那么将其设为本地实例就非常好(换句话说,只需使用 var rng = new SecureRandom(),甚至 new SecureRandom() 如果您 需要它的单个 方法调用)。

我完全同意Maartens 的回答。但是,可以注意到 java.util 类 为 SecureRandom 本身创建了静态。

public final class UUID implements java.io.Serializable, Comparable<UUID> {

    ...

    /*
     * The random number generator used by this class to create random
     * based UUIDs. In a holder class to defer initialization until needed.
     */
    private static class Holder {
        static final SecureRandom numberGenerator = new SecureRandom();
    }