随机数生成器在创建新对象时返回相同的结果

时间:2019-11-14 10:35:35

标签: java random

我目前正在自学Java,实践问题的最终输出之一需要为不同的对象使用不同的名称(这是根据随机数生成器确定的)。但是,每次创建对象时,这些对象最终都会使用相同的名称。为了给出一个清晰的例子,下面是示例输出:

Expected Output

以下是我的输出:

enter image description here

正如我的输出突出显示的那样,我所有的动物都具有相同的名称,而预期的输出具有不同的名称。我已经测试了多次,可以确认这不是由于运气造成的。

下面是我的Cow类的代码,该代码构造名称和其他信息(我省略了不相关的方法):

import java.lang.Math;
import java.util.Random;

public class Cow implements Milkable, Alive {
    private String name;
    private double capacity;
    private double amount;

    private static final String[] NAMES = new String[]{
        "Anu", "Arpa", "Essi", "Heluna", "Hely",
        "Hento", "Hilke", "Hilsu", "Hymy", "Ihq", "Ilme", "Ilo",
        "Jaana", "Jami", "Jatta", "Laku", "Liekki",
        "Mainikki", "Mella", "Mimmi", "Naatti",
        "Nina", "Nyytti", "Papu", "Pullukka", "Pulu",
        "Rima", "Soma", "Sylkki", "Valpu", "Virpi"};

    private static final String randName = NAMES[new Random().nextInt(NAMES.length)];

    // Default Constructor <- where issue is
    public Cow(){
        this(randName);
    }

    // Overloaded Constructor
    public Cow(String name){
        this.name = name;   
        this.capacity = (15.0 + new Random().nextInt(26)); 
        this.amount = 0.0;
    }

    // accessors...
    // milk... removes milk from cow's tank (implements Milkable interface)
    // liveHour... adds milk to cow's tank (implements Alive interface)
    // toString...
}

此外,这是我上面使用的主要类(同样,省略了不必要的部分):

        Farm farm = new Farm("Esko", new Barn(new BulkTank()));

        farm.addCow(new Cow());
        farm.addCow(new Cow());
        farm.addCow(new Cow());

        System.out.println(farm);

This post表示,如果在构造函数上已经设置了种子,则随机数生成器最终将是确定性的。但是,我的随机数生成器必须具有特定的种子(在这种情况下,数组的长度包含随机名称)才能选择随机名称。我想知道是否有人知道让我的随机数生成器产生新值的方法。预先谢谢你。

3 个答案:

答案 0 :(得分:8)

问题是这一行:

private static final String randName = NAMES[new Random().nextInt(NAMES.length)];

您将randName定义为静态变量,该静态变量绑定到类而不是实例,这意味着Cow的每个实例都具有相同的randName

在默认构造函数中,您应该具有:

public Cow(){
    this(NAMES[new Random().nextInt(NAMES.length)]);
}

答案 1 :(得分:1)

randName 被声明为静态的,可能会导致问题。静态字段在类加载时仅加载一次。尝试将其声明为实例变量(非静态)

答案 2 :(得分:1)

除了hotzst的答案外,没有理由为您创建的Random的每个实例创建一个新的Cow实例。

例如,您可以如下定义名称生成器:

private static final Random random = new Random();
private static final Supplier<String> namesGenerator = () -> NAMES[random.nextInt(NAMES.length)];

现在,您可以使用以下方法实例化Cow

public Cow() {
    this(namesGenerator.get());
}