Summary
Provide an adapter so that any RandomGenerator
can be used where an instance of Random
is required. Adjust other areas of the Random
class specification to provide flexibility to subclasses.
Problem
JEP 356 introduced the RandomGenerator
interface as well as a collection of new pseudorandom number generation algorithms and support APIs. However, many APIs consume an instance of java.util.Random
; they cannot be used if one has an instance of RandomGenerator
. This includes some APIs in the JDK:
- two
BigInteger
constructors BigInteger::probablePrime
Collections::shuffle
Eventually these may be retrofitted to consume RandomGenerator
, but they aren't as yet. In third-party libraries, it might be difficult to retrofit Random
-consuming APIs also to consume RandomGenerator
if those libraries need to run on Java SE releases prior to the integration of JEP 356.
An issue that emerged from this work was how to handle the setSeed
method. Its current specification imposes a requirement of setting the entire state of the generator, which in general is not possible for an arbitrary RandomGenerator
instance. The setSeed
method in the existing subclass SecureRandom
uses the seed value to update but not to set its entire state. The existing subclass ThreadLocalRandom
rejects calls to the setSeed
method entirely. These inconsistencies between the specification and actual behavior should be rectified.
The protected method next(int)
is intended to be overridden by subclasses, but it appears to impose a general contract on subclasses. This inconsistency should be clarified.
Solution
Add a method that takes a RandomGenerator
instance and wraps it inside a Random
instance. The random-producing methods of the returned Random
instance are delegated to the enclosed RandomGenerator
instance.
Adjust the specification of the setSeed
method to allow flexibility or non-implementation by subclasses, including the wrapper class introduced here.
Clarify the specification of the protected next(int)
method.
Specification
Add the following method to the java.util.Random
class:
/**
* Returns an instance of {@code Random} that delegates method calls to the {@link RandomGenerator}
* argument. If the generator is an instance of {@code Random}, it is returned. Otherwise, this method
* returns an instance of {@code Random} that delegates all methods except {@code setSeed} to the generator.
* The returned instance's {@code setSeed} method always throws {@link UnsupportedOperationException}.
* The returned instance is not serializable.
*
* @param generator the {@code RandomGenerator} calls are delegated to
* @return the delegating {@code Random} instance
* @throws NullPointerException if generator is null
* @since 19
*/
public static Random from(RandomGenerator generator)
Modify the specification of the Random::setSeed
method as follows:
/**
* Sets or updates the seed of this random number generator using the
* provided {@code long} seed value (optional operation).
*
* @implSpec
* The implementation in this class alters the state of this random number
* generator so that it is in the same state as if it had just been created with
* {@link #Random(long) new Random(seed)}. It atomically updates the seed to
* <pre>{@code (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1)}</pre>
* and clears the {@code haveNextNextGaussian} flag used by {@link #nextGaussian}.
* Note that this uses only 48 bits of the given seed value.
*
* @param seed the seed value
* @throws UnsupportedOperationException if the {@code setSeed}
* operation is not supported by this random number generator
*/
public synchronized void setSeed(long seed)
Modify the specification of the Random::next
method as follows:
/**
* Generates the next pseudorandom number. This method returns an
* {@code int} value such that, if the argument {@code bits} is between
* {@code 1} and {@code 32} (inclusive), then that many low-order
* bits of the returned value will be (approximately) independently
* chosen bit values, each of which is (approximately) equally
* likely to be {@code 0} or {@code 1}.
*
* @apiNote
* The other random-producing methods in this class are implemented
* in terms of this method, so subclasses can override just this
* method to provide a different source of pseudorandom numbers for
* the entire class.
*
* @implSpec
* The implementation in this class atomically updates the seed to
* <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}</pre>
* and returns
* <pre>{@code (int)(seed >>> (48 - bits))}.</pre>
*
* <p>This is a linear congruential pseudorandom number generator, as
* defined by D. H. Lehmer and described by Donald E. Knuth in
* <cite>The Art of Computer Programming, Volume 2, Third edition:
* Seminumerical Algorithms</cite>, section 3.2.1.
*
* @param bits random bits
* @return the next pseudorandom value from this random number
* generator's sequence
* @since 1.1
*/
protected int next(int bits)
- csr of
-
JDK-8279598 provide adapter from RandomGenerator to Random
-
- Resolved
-
- relates to
-
JDK-8288596 Random:from() adapter does not delegate to supplied generator in all cases
-
- Closed
-