简体   繁体   English

为什么不能在子类构造函数中添加额外的参数验证?

[英]Why can't I add extra argument validation in the subclass constructor?

I have two classes. 我有两节课。 The superclass: 超类:

public abstract class Question(){

public Question(String question, String answer, String... alts){...
}

And the subclass: 和子类:

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);
}}

I want my subclass, StringOptionsQuestion , to validate the length of alts before it passes it on to the superclass' constructor. 我希望我的子类StringOptionsQuestion在将alts的长度传递给超类的构造函数之前对其进行验证。 However, I can't do it this way. 但是,我不能这样做。 I get the error "Constructor call must be the first statement in a constructor". 我收到错误消息“构造函数调用必须是构造函数中的第一条语句”。 Why does this error exist? 为什么会出现此错误? And how can I bypass it in my case? 我该如何绕过它呢?

As kocko notes, the super statement must be the first statement in your constructor. 如kocko所述, super语句必须是构造函数中的第一条语句 However, if you really, really don't want to get as far as the superconstructor before validating (eg because it will blow up with a less-helpful error), you can validate while evaluating the arguments to the superconstructor: 但是,如果您确实真的不想在验证之前深入到超构造函数(例如,因为它会因无济于事的错误而崩溃),则可以在评估超构造函数的参数时进行验证:

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;
    }
}

The super() statement must be the first one in your constructor: super()语句必须是构造函数中的第一个:

super(question, answer, alts);
if (alts.length == 0) { 
    throw new IllegalArgumentException();
}

As others have said, the call to super(...) must be the first statement in a subclass constructor. 正如其他人所说,对super(...)的调用必须是子类构造函数中的第一条语句。

However, it doesn't have to be the first expression that is being evaluated. 但是,它不必是要求值的第一个表达式

If you really need to do something before you call the superclass constructor (and this is not standard code - you should really document why you are doing this if you are) then you can do something like this, by calling a static method as an expression: 如果在调用超类构造函数之前确实需要做一些事情(这不是标准代码,则应该记录为什么这样做),然后可以通过调用静态方法作为表达式来做类似的事情:

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));
    }
}

Super class constructor will be always called. 超级类构造函数将始终被调用。 Either you explicitly calls it or java does it for you. 您可以显式调用它,也可以由Java为您执行。 And when you do it explicitly from your subclass constructor it has to be the first thing in your constructor. 而且,当您从子类构造函数中显式执行此操作时,它必须是构造函数中的第一件事。

I am not sure what exactly is your requirement, but my guess is you want to avoid constructing the object in the case of your StringOptionsQuestion subclass if alts.length == 0. You can achieve this by adding another constructor in your super class which takes an extra boolean parameter say 'checkLength' and if its value is true validate for length and throw the exception if needed. 我不确定您的要求到底是什么,但是我想是如果alts.length == 0,则要避免在StringOptionsQuestion子类的情况下构造对象。您可以通过在超级类中添加另一个构造函数来实现此目的,一个额外的布尔参数,例如'checkLength',如果其值为true,则对长度进行验证,并在需要时抛出异常。 Then from your StringOptionsQuestion subclass call the new constructor. 然后从您的StringOptionsQuestion子类中调用新的构造函数。

public abstract class Question(){ 公共抽象类Question(){

public Question(String question, String answer, String... alts){... } 公共问题(字符串问题,字符串答案,字符串...替代项){...}

public Question(String question, String answer, String... alts, boolean checkLength){ 公共问题(字符串问题,字符串答案,字符串...替代项,布尔值checkLength){

if (checkLength && alts.length == 0){throw new IllegalArgumentException();} if(checkLength && alts.length == 0){引发新的IllegalArgumentException();}

} }

} }

public class StringOptionsQuestion extends Question { 公共类StringOptionsQuestion扩展了问题{

public StringOptionsQuestion(String question, String answer, String... alts){ 公共StringOptionsQuestion(字符串问题,字符串答案,字符串...替代项){

super(question, answer, alts, true);

}} }}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM