-
Enhancement
-
Resolution: Won't Fix
-
P4
-
None
-
8u72
-
generic
-
generic
A DESCRIPTION OF THE REQUEST :
Method "setSeed(long)" is public, overridable, and called by the constructors of the class.
JUSTIFICATION :
Quoting J. Bloch ("Effective Java"):
"There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly."
A use-case is to create a subclass of "Random" in order to forbid reseeding of the generator.
The obvious way is to override "setSeed" and make it raise an exception.
But it does not work because "setSeed" is called by the base class' constructor.
This is one example but other bugs can result if the overridden "setSeed" relies on instance variables defined in the subclass (whose instance is not initialized when the "Random" constructor runs).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The constructor should set the seed without calling the public method "setSeed".
No overridable method should run before the object is completely initialized.
ACTUAL -
Method "setSeed" is run before the object is completely initialized.
---------- BEGIN SOURCE ----------
import java.util.Random;
public class JDKRandomAdaptor extends Random {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160326L;
public JDKRandomAdaptor(long seed) {
super(seed);
}
@Override
protected int next(int bits) {
return super.nextInt();
}
@Override
public void setSeed(long seed) {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
new JavaUtilRandom(122333444L);
}
}
---------- END SOURCE ----------
Method "setSeed(long)" is public, overridable, and called by the constructors of the class.
JUSTIFICATION :
Quoting J. Bloch ("Effective Java"):
"There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly."
A use-case is to create a subclass of "Random" in order to forbid reseeding of the generator.
The obvious way is to override "setSeed" and make it raise an exception.
But it does not work because "setSeed" is called by the base class' constructor.
This is one example but other bugs can result if the overridden "setSeed" relies on instance variables defined in the subclass (whose instance is not initialized when the "Random" constructor runs).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The constructor should set the seed without calling the public method "setSeed".
No overridable method should run before the object is completely initialized.
ACTUAL -
Method "setSeed" is run before the object is completely initialized.
---------- BEGIN SOURCE ----------
import java.util.Random;
public class JDKRandomAdaptor extends Random {
/** Serializable version identifier. */
private static final long serialVersionUID = 20160326L;
public JDKRandomAdaptor(long seed) {
super(seed);
}
@Override
protected int next(int bits) {
return super.nextInt();
}
@Override
public void setSeed(long seed) {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
new JavaUtilRandom(122333444L);
}
}
---------- END SOURCE ----------
- relates to
-
JDK-8279598 provide adapter from RandomGenerator to Random
-
- Resolved
-