为什么我不能在子类构造函数中添加额外的参数验证?
Why can't I add extra argument validation in the subclass constructor?
我有两个类。超类:
public abstract class Question(){
public Question(String question, String answer, String... alts){...
}
和子类:
public class StringOptionsQuestion extends Question {
public StringOptionsQuestion(String question, String answer, String... alts){
if (alts.length == 0){throw new IllegalArgumentException();} //The compiler doesn't like this line.
super(question, answer, alts);
}}
我希望我的子类 StringOptionsQuestion
在将 alts
的长度传递给超类的构造函数之前验证它的长度。但是,我不能这样做。我收到错误 "Constructor call must be the first statement in a constructor"。为什么会出现这个错误?在我的案例中如何绕过它?
super()
语句 必须 是构造函数中的第一个:
super(question, answer, alts);
if (alts.length == 0) {
throw new IllegalArgumentException();
}
正如 kocko 指出的那样,super
语句必须是构造函数中的第一个 语句。但是,如果您真的、真的不想在验证之前达到超构造函数那么远(例如,因为它会因一个不太有用的错误而爆炸),您可以在评估超构造函数的参数时进行验证:
public class StringOptionsQuestion extends Question {
public StringOptionsQuestion(String question, String answer, String... alts) {
super(question, answer, validateAlternatives(alts));
}
private static String[] validateAlternatives(String[] alternatives) {
if (alternatives.length == 0) {
throw new IllegalArgumentException();
}
return alternatives;
}
}
正如其他人所说,对 super(...)
的调用必须 是子类构造函数中的第一条语句。
但是,它不一定是要计算的第一个 表达式。
如果你真的需要在调用超类构造函数之前做一些事情(这不是标准代码——如果你是的话,你应该真正记录你为什么这样做)然后你可以通过调用一个静态方法作为表达式来做这样的事情:
public class StringOptionsQuestion extends Question {
private static String[] checkAlts(String[] alts) {
if (alts.length == 0) {
throw new IllegalArgumentException();
}
return alts;
}
public StringOptionsQuestion(String question, String answer, String... alts) {
super(question, answer, checkAlts(alts));
}
}
超级class 构造函数将始终被调用。要么你明确地调用它,要么 java 为你做。当您从 subclass 构造函数中显式执行此操作时,它必须是构造函数中的第一件事。
我不确定您的具体要求是什么,但我的猜测是您想避免在 StringOptionsQuestion subclass if alts.length == 0 的情况下构造对象。您可以通过在你的 super class 中添加另一个构造函数来实现这一点,它需要一个额外的布尔参数,比如 'checkLength' 并且如果它的值是 true 验证长度并在需要时抛出异常。然后从您的 StringOptionsQuestion subclass 调用新的构造函数。
public 摘要 class 问题(){
public 问题(字符串问题,字符串答案,字符串...替代){...
}
public 问题(字符串问题,字符串答案,字符串...替代,布尔检查长度){
if (checkLength && alts.length == 0){抛出新的 IllegalArgumentException();}
}
}
public class StringOptionsQuestion 扩展问题 {
public StringOptionsQuestion(字符串问题,字符串答案,字符串...替代){
super(question, answer, alts, true);
}}
我有两个类。超类:
public abstract class Question(){
public Question(String question, String answer, String... alts){...
}
和子类:
public class StringOptionsQuestion extends Question {
public StringOptionsQuestion(String question, String answer, String... alts){
if (alts.length == 0){throw new IllegalArgumentException();} //The compiler doesn't like this line.
super(question, answer, alts);
}}
我希望我的子类 StringOptionsQuestion
在将 alts
的长度传递给超类的构造函数之前验证它的长度。但是,我不能这样做。我收到错误 "Constructor call must be the first statement in a constructor"。为什么会出现这个错误?在我的案例中如何绕过它?
super()
语句 必须 是构造函数中的第一个:
super(question, answer, alts);
if (alts.length == 0) {
throw new IllegalArgumentException();
}
正如 kocko 指出的那样,super
语句必须是构造函数中的第一个 语句。但是,如果您真的、真的不想在验证之前达到超构造函数那么远(例如,因为它会因一个不太有用的错误而爆炸),您可以在评估超构造函数的参数时进行验证:
public class StringOptionsQuestion extends Question {
public StringOptionsQuestion(String question, String answer, String... alts) {
super(question, answer, validateAlternatives(alts));
}
private static String[] validateAlternatives(String[] alternatives) {
if (alternatives.length == 0) {
throw new IllegalArgumentException();
}
return alternatives;
}
}
正如其他人所说,对 super(...)
的调用必须 是子类构造函数中的第一条语句。
但是,它不一定是要计算的第一个 表达式。
如果你真的需要在调用超类构造函数之前做一些事情(这不是标准代码——如果你是的话,你应该真正记录你为什么这样做)然后你可以通过调用一个静态方法作为表达式来做这样的事情:
public class StringOptionsQuestion extends Question {
private static String[] checkAlts(String[] alts) {
if (alts.length == 0) {
throw new IllegalArgumentException();
}
return alts;
}
public StringOptionsQuestion(String question, String answer, String... alts) {
super(question, answer, checkAlts(alts));
}
}
超级class 构造函数将始终被调用。要么你明确地调用它,要么 java 为你做。当您从 subclass 构造函数中显式执行此操作时,它必须是构造函数中的第一件事。
我不确定您的具体要求是什么,但我的猜测是您想避免在 StringOptionsQuestion subclass if alts.length == 0 的情况下构造对象。您可以通过在你的 super class 中添加另一个构造函数来实现这一点,它需要一个额外的布尔参数,比如 'checkLength' 并且如果它的值是 true 验证长度并在需要时抛出异常。然后从您的 StringOptionsQuestion subclass 调用新的构造函数。
public 摘要 class 问题(){
public 问题(字符串问题,字符串答案,字符串...替代){... }
public 问题(字符串问题,字符串答案,字符串...替代,布尔检查长度){
if (checkLength && alts.length == 0){抛出新的 IllegalArgumentException();}
}
}
public class StringOptionsQuestion 扩展问题 {
public StringOptionsQuestion(字符串问题,字符串答案,字符串...替代){
super(question, answer, alts, true);
}}