天天看點

java random 種子數_Java 解惑:Random 種子的作用、含參與不含參構造函數差別

Random 通常用來作為随機數生成器,它有兩個構造方法:

Random random = new Random();

Random random2 = new Random(50);

1.不含參構造方法:

public Random() {

setSeed(System.nanoTime() + seedBase);

++seedBase;

}

2.含參構造方法:

public Random(long seed) {

setSeed(seed);

}

都調用的 setSeed 方法:

public synchronized void setSeed(long seed) {

this.seed = (seed ^ multiplier) & ((1L << 48) - 1);

haveNextNextGaussian = false;

}

可以看到,不含參構造方法每次都使用目前時間作為種子,而含參構造方法是以一個固定值作為種子

什麼是種子 seed 呢?

seed 是 Random 生成随機數時使用的參數:

Random 中最重要的就是 next(int) 方法,使用 seed 進行計算:

protected synchronized int next(int bits) {

seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);

return (int) (seed >>> (48 - bits));

}

其他 nextXXX 方法都是調用的 next()。

比如 nextInt(int):

public int nextInt(int n) {

if (n <= 0) {

throw new IllegalArgumentException("n <= 0: " + n);

}

if ((n & -n) == n) {

//調用 next()

return (int) ((n * (long) next(31)) >> 31);

}

int bits, val;

do {

bits = next(31);

val = bits % n;

} while (bits - val + (n - 1) < 0);

return val;

}

再比如 nextBoolean():

//也是調用的 next()

public boolean nextBoolean() {

return next(1) != 0;

}

舉個栗子:

@Test

public void testRandomParameter(){

System.out.println("Random 不含參構造方法:");

for (int i = 0; i < 5; i++) {

Random random = new Random();

for (int j = 0; j < 8; j++) {

System.out.print(" " + random.nextInt(100) + ", ");

}

System.out.println("");

}

System.out.println("");

System.out.println("Random 含參構造方法:");

for (int i = 0; i < 5; i++) {

Random random = new Random(50);

for (int j = 0; j < 8; j++) {

System.out.print(" " + random.nextInt(100) + ", ");

}

System.out.println("");

}

}

分别用含參構造方法和不含參構造方法建立 5 個随機生成器對象,每個随機生成器再生産 8 個随機數,對比下結果:

java random 種子數_Java 解惑:Random 種子的作用、含參與不含參構造函數差別

再運作一次:

java random 種子數_Java 解惑:Random 種子的作用、含參與不含參構造函數差別

總結:

通過上述例子可以發現:

随機數是種子經過計算生成的。

不含參的構造函數每次都使用目前時間作為種子,随機性更強

而含參的構造函數其實是僞随機,更有可預見性