1

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. 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?

Magnus
  • 589
  • 8
  • 26

4 Answers4

5

As kocko notes, the super statement must be the first statement in your constructor. However, if you really, really don't want to get as far as the superconstructor before validating (e.g. 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;
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

The super() statement must be the first one in your constructor:

super(question, answer, alts);
if (alts.length == 0) { 
    throw new IllegalArgumentException();
}
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • 1
    This doesn't satisfy the OP's request to validate the length before it passes it onto the superclass constructor. Most of the time this approach is fine, but sometimes you really do want to validate first - and you can, in many cases, as per my answer. – Jon Skeet May 21 '15 at 13:09
1

As others have said, the call to super(...) must be the first statement in a subclass constructor.

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));
    }
}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
0

Super class constructor will be always called. Either you explicitly calls it or java does it for you. 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. Then from your StringOptionsQuestion subclass call the new constructor.

public abstract class Question(){

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

public Question(String question, String answer, String... alts, boolean checkLength){

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

}

}

public class StringOptionsQuestion extends Question {

public StringOptionsQuestion(String question, String answer, String... alts){

super(question, answer, alts, true);

}}

gipsy
  • 3,859
  • 1
  • 13
  • 21