1. 程式人生 > >Java Random 含參與不含參構造函數的區別

Java Random 含參與不含參構造函數的區別

什麽是 cep zed xxx 結果 對比 target pri urn

##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 含參與不含參構造函數的區別