我有以下java代码
public class QuestionBuilder {
private QuestionBuilder(){}
static HashMap<Long,Class<? extends Question>> questionIdMap;
static{
questionIdMap = new HashMap();
questionIdMap.put(1L, LicenseNumberQuestion.class);
questionIdMap.put(2L, USPQuestion.class);
}
static Question getQuestion(long questionId)
{
if(!questionIdMap.containsKey(questionId))
{
throw new BusinessProfileInputException("Add an id to question class map entry");
}
return questionIdMap.get(questionId).newInstance();
}
}
我希望我的getQuestion方法能够返回一个新的类实例,该实例在地图中指定为通过我的代码预期的值。 Howerver最后一行代码无法编译:
return questionIdMap.get(questionId).newInstance();
我是否错误地想到了这个?即有更好的方法来解决这个问题吗?
答案 0 :(得分:1)
你只需要捕获一个例外:
try {
return questionIdMap.get(questionId).newInstance();
} catch(InstantiationException e) {
System.out.println("Constructor failed: );
e.printStackTrace();
return null;
}
这应该编译得很好。
答案 1 :(得分:0)
我会这样做:
public final class QuestionBuilder {
private QuestionBuilder(){}
public enum Type {
LICENSE_NUMBER {
@Override
Question getQuestion() { return new LicenseNumberQuestion(); }
},
USP {
@Override
Question getQuestion() { return new USPQuestion(); }
};
abstract Question getQuestion();
}
public static Question getQuestion(Type type) {
return type.getQuestion();
}
}
使用您的解决方案,该类用户必须编写
Question question = QuestionBuilder.getQuestion(1);
这并不是很好,因为它不清楚是什么&#34; 1&#34;这意味着,她将不得不学习一大堆数字的含义。另外,如果你输入一个并不代表任何内容的数字,那么就会出现问题(因此需要BusinessProfileInputException
)。
使用enum
方法,该类的用户将编写
Question question = QuestionBuilder.getQuestion(QuestionBuilder.Type.LICENSE_NUMBER);
现在这显然更长,但有三大优势。 (1)班级用户不需要记住任何抽象代码。实际上,如果用户使用的是体面的IDE,那么在她输入时,实际上应该向她提供一个有意义的选择列表。 (2)不再需要BusinessProfileInputException
因为现在不可能传递的东西并不代表任何东西(null
除外),但在此案例a NullPointerException
无论如何都会被抛出)。 (3)您不再需要反射来创建新的Question
,因此不需要恼人的try
阻止。
但它甚至比这更好。您注意到,由于我们已经摆脱Map
,因此课程QuestionBuilder
实际上并没有任何。您可以通过完全删除课程来进一步改进,并使enum
成为顶级课程,使用简单的名称TypeOfQuestion
。然后所有用户都必须输入
Question question = TypeOfQuestion.LICENSE_NUMBER.getQuestion();
Java中的 enum
非常棒。它们远远优于其他语言的同行。我强烈建议您了解它们。