Home > Mobile >  Is there a java annotation for function ending the program? Get rid of "missing return statemen
Is there a java annotation for function ending the program? Get rid of "missing return statemen

Time:10-05

I have the following code

public enum Animal {
    DOG,CAT;
    
    private void exitWithError(String message){
        System.out.println(message);
        System.exit(1);
    }
    
    @Override
    public String toString() {
        switch(this){
            case DOG:
                return "dog";
            case CAT:
                return "cat";
            default:
                //                missing return statement error
                exitWithError("unrecognized animal");

/*
                 workaround - don't like it
                 return null;
 */

/*               no error if exception thrown
                 throw new IllegalStateException("unrecognized animal");

 */

        }
    }
}

The above code results in a missing return statement error. I have some questions:

  1. The exitWithError method should always finish program execution, right?

  2. If the method always exits, is there any way I can inform the compiler about it so it doesn't throw the missing return statement at me?

The return null workaround seems to be bad code as if the code changed and this return statement would get executed it could cause problems.

CodePudding user response:

A toString() method should never exit the program. More generally, almost no methods should attempt to exit the program.

Think about how surprising it would be for System.out.println(EnumSet.allOf(Animal.class)); to cause the program to quit. (It wouldn't, now, but it might if you added another Animal and forgot to update toString()).

If you want to indicate something is wrong here, throw an exception (or an error), which allows callers to deal with it, if they are able to:

@Override
public String toString() {
    switch(this){
        case DOG:
            return "dog";
        case CAT:
            return "cat";
    }
    throw new AssertionError();
}

The throw is actually unreachable, but the compiler doesn't know this: the throw is necessary to convince the compiler that the method cannot complete normally (i.e. without returning a value or throwing).

Or, in Java 12 , the compiler will check for the completeness of a switch expression over an enum:

return switch (this) {
  DOG -> "dog";
  CAT -> "cat";
})

However, an alternative approach (usable pre-Java 12) would be to make the toString() a parameter of the constructor, so you never have to worry about having an Animal without a known toString():

enum Animal {
  DOG("dog"), CAT("cat");

  private String string;

  Animal(String string) { this.string = string; }

  @Override public String toString() { return string; }
}
  • Related