播种Java时的奇怪行为

播种Java时的奇怪行为,java,random,Java,Random,以下代码应创建两个具有相同种子的随机对象: System.out.println("System time before: " + System.currentTimeMillis()); Random r1 = new Random(); Random r2 = new Random(System.currentTimeMillis()); System.out.println("System time after: " + System.currentTimeMillis()); Syst

以下代码应创建两个具有相同种子的随机对象:

System.out.println("System time before: " + System.currentTimeMillis());
Random r1 = new Random();
Random r2 = new Random(System.currentTimeMillis());
System.out.println("System time after: " + System.currentTimeMillis());

System.out.println("r1: " + r1.nextInt());
System.out.println("r2: " + r2.nextInt());

种子应该是相同的,因为在创建两个对象之前和之后,
System.currentTimeMillis()
没有改变,如输出所示:

System time before: 1331889186449
System time after: 1331889186449
r1: -1836225474
r2: 2070673752
从文档中可以看出,没有任何参数的构造函数只是:

public Random() { this(System.currentTimeMillis()); }
那么是什么原因呢?有人能解释为什么这两个生成器在具有相同种子时返回不同的输出吗

两个生成器在应该具有相同种子时返回不同的输出


是吗?在我看来,只有一个生成器获得了millis种子…

如果您使用的是java.util.Random,这是我看到的默认无参数构造函数-现在它可能取决于您使用的JDK版本(此代码似乎至少用于sun JDK 6和7):

为了确认这一点,这里有一个代码来检查种子是否相同:

public static void main(String args[]) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    System.out.println("System time before: " + System.currentTimeMillis());
    Random r1 = new Random();
    Random r2 = new Random(System.currentTimeMillis());
    System.out.println("System time after: " + System.currentTimeMillis());

    Field seed = Random.class.getDeclaredField("seed");
    seed.setAccessible(true);
    AtomicLong seed1 = (AtomicLong) seed.get(r1);
    AtomicLong seed2 = (AtomicLong) seed.get(r2);

    System.out.println("seed1 = " + seed1);
    System.out.println("seed2 = " + seed2);
}

我不认为默认构造函数会像你说的那样(即,
public Random{this(System.currentTimeMillis());}
java文档只是说它在初始化类时使用的值在每次调用时都可能不同


我的快速谷歌搜索带来了-你在哪里找到的?@Andrew,这是来自Java 1.4.2的经验教训是不要依赖类或方法的内部定义来实现自己的逻辑。教我不要使用IDE…所以Eclipse给了我
public Random(){this(++seedUniquifier+System.nanoTime();}
这就是@Roman在下面发布的内容。我想知道为什么这与你的答案不同?@Andrew,因为你可能在使用不同的JDK…他在Max OS X上,我在Windows上,不知道有什么不同。在大多数IDE中,你可以做
+
来查看方法的源代码。“种子应该是相同的,因为在创建两个对象之前和之后,
System.currentTimeMillis()
没有更改”-不能保证这是真的。
public static void main(String args[]) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    System.out.println("System time before: " + System.currentTimeMillis());
    Random r1 = new Random();
    Random r2 = new Random(System.currentTimeMillis());
    System.out.println("System time after: " + System.currentTimeMillis());

    Field seed = Random.class.getDeclaredField("seed");
    seed.setAccessible(true);
    AtomicLong seed1 = (AtomicLong) seed.get(r1);
    AtomicLong seed2 = (AtomicLong) seed.get(r2);

    System.out.println("seed1 = " + seed1);
    System.out.println("seed2 = " + seed2);
}
public Random() { this(++seedUniquifier + System.nanoTime()); }