我必须将我的代码更改为使用反射来生成随机参数的解决方案。
我不知道如何实现这个......
这是类生成器:
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/