java - 如何用随机生成的参数填充随机选择的类对象?

标签 java random generator

我必须将我的代码更改为使用反射来生成随机参数的解决方案。

我不知道如何实现这个......

这是类生成器:

public class SweetsGenerator implements Generator<Sweets>, Iterable<Sweets> {

    private static final Logger LOG = Logger.getLogger(SweetsGenerator.class);

    @SuppressWarnings("rawtypes")
    private Class[] types = { 
        WhiteChocolate.class, MilkChokolate.class,  DarkChocolate.class, 
        DesertChocolate.class, PorousChocolate.class, 
    };

    private static Random rand = new Random();

    public SweetsGenerator() {
    }

    private int size = 0;

    public SweetsGenerator(int sz) {
        size = sz;
    }

    public Sweets next() {
        try {
            return (Sweets) types[rand.nextInt(types.length)].newInstance();
        } catch (Exception e) {
            LOG.error("RuntimeException", e);
            throw new RuntimeException(e);
        }
    }

    class SweetsIterator implements Iterator<Sweets> {
        int count = size;

        public boolean hasNext() {
            return count > 0;
        }

        public Sweets next() {
            count--;
            return SweetsGenerator.this.next();
        }

        public void remove() { // Not implemented
            LOG.error("UnsupportedOperationException");
            throw new UnsupportedOperationException();
        }
    };

    public Iterator<Sweets> iterator() {
        return new SweetsIterator();
    }
}

如何规避这种方法并创建新的类元素,例如:

new WhiteChocolate((rand.nextDouble() * 100) + 1, (rand.nextDouble() * 200) + 1);

我不能将它与我们可以创建的随机生成类女巫元素结合起来。

这是 Sweets 抽象类的内容及其实现之一:

public abstract class Sweets {

    private double sugarLevel;

    private double weight;

    public double getSugarLevel() {
        return sugarLevel;
    }

    public double getWeight() {
        return weight;
    }

    public void setSugarLevel(double sugarLevel) {
        this.sugarLevel = sugarLevel;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName() + " " + sugarLevel + " " + weight);
        return sb.toString();
    }   
}

public class Chocolate extends Sweets {

    public Chocolate() {
    }

    public Chocolate(double aSugarLevel, double aWeight) {
        setSugarLevel(aSugarLevel);
        setWeight(aWeight);
    }
}

更新:

我尝试根据 skiwi 建议修改 next()

接下来是更改的版本:

public Sweets next() {
    Sweets current = instances[rand.nextInt(instances.length)];
    Double param1 = (rand.nextDouble() * 100) + 1;
    Double param2 = (rand.nextDouble() * 200) + 1;
    System.out.println("parameters: " + Math.round(param1) + " " + Math.round(param2));

    try {
        return (Sweets) current.getClass()
                .getConstructor(Double.class, Double.class)
                .newInstance(Math.round(param1), Math.round(param2));
        // Report programmer errors at run time:
    } catch (Exception e) {
        LOG.error("RuntimeException", e);
        throw new RuntimeException(e);
    }
}

但它抛出了下一组异常:

23:25:51,337 ERROR main SweetsGenerator:next:52 - RuntimeException
 java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
    at java.lang.Class.getConstructor0(Class.java:2800)
    at java.lang.Class.getConstructor(Class.java:1708)
    at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:48)
    at com.epam.lab.NewYearGift.generate(NewYearGift.java:37)
    at com.epam.lab.GiftList.generateGift(GiftList.java:47)
    at com.epam.lab.GiftList.main(GiftList.java:59)
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
    at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:53)
    at com.epam.lab.NewYearGift.generate(NewYearGift.java:37)
    at com.epam.lab.GiftList.generateGift(GiftList.java:47)
    at com.epam.lab.GiftList.main(GiftList.java:59)
Caused by: java.lang.NoSuchMethodException: com.epam.lab.chocolate.DarkChocolate.<init>(java.lang.Double, java.lang.Double)
    at java.lang.Class.getConstructor0(Class.java:2800)
    at java.lang.Class.getConstructor(Class.java:1708)
    at com.epam.lab.SweetsGenerator.next(SweetsGenerator.java:48)
    ... 3 more

此问题的解决方案是更改一行:

return (Sweets) current.getClass().getConstructor(double.class, double.class) .newInstance(Math.round(param1), Math.round(param2));

如何保护生成器的逻辑并使用参数创建随机元素?

有什么建议吗?

最佳答案

如果您有类似 public WhiteChololate(Double a, Double b) 的构造函数合约,您可以调用以下命令来创建一个新实例:

Double a = 1d;
Double b = 2d;
WhiteChocolate.class.getConstructor(Double.class, Double.class).newInstance(a, b);

这将构造所需的实例,而不是我在Class<?>.newInstance()上使用此语法。 ,因为如上所述 here :

Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException.

所以使用Constructor.newInstance(...)既更安全,也是唯一能满足您需求的。

请注意,您需要在 .getConstructor() 中指定参数类型调用,但还没有值。

关于java - 如何用随机生成的参数填充随机选择的类对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20526581/

相关文章:

java - Android-值未插入数据库

java - 如何贡献 Action 与 Eclipse 中的菜单进行比较

c# - 随机概率选择

sql-server - 使用 LINQ(ala TABLESAMPLE)从大型结果集中有效地选择随机行

python - 如果 range() 是 Python 3.3 中的生成器,为什么我不能在范围上调用 next()?

java - 是否有用于包装和修改响应的 Java EE 过滤器?

java - 无法选择下拉选项(selenide/java)

c - 生成数组中的随机数并计算平均值、最大值、最小值、总和

php - 如何使用 PHP 在服务器上保存 CSS 图像