Suppose, we have switch statement, that fully covers all possible cases of enum parameter, and has null-check too, will not be compiled cause of "Missing return statement"
.
enum Foo {ONE,TWO}
int fooToInt(Foo foo) {
if (foo == null) {
throw new NullPointerException();
}
switch (foo) {
case ONE: return 1;
case TWO: return 2;
}
}
I know, that throwing exception from default
case or after enum, or visiting enum element instead of switch
will fix the problem. But I do not understand technical cause of such behavior: obviously, there is no possible branch of execution, which not leads to return
or throw
. Also it would be great in some cases to have compile-time check that all cases are covered.
How to resolve the error? In order to solve the missing return statement error, we simply need to add the return statement to the method just like to the one we did in case one. So, we will return the some value of the same type which we used before the name like as: public static String checkNumber( int number) {
We can use also use Enum keyword with Switch statement. We can use Enum in Switch case statement in Java like int primitive.
The “missing return statement” message occurs when a method does not have a return statement. Each method that returns a value (a non-void type) must have a statement that literally returns that value so it can be called outside the method.
Java Enum valueOf()The valueOf() method takes a string and returns an enum constant having the same string name. For example, Size. valueOf("SMALL") // returns constant SMALL.
I'm going to take a shot in the dark here, having not read any rationale for this, but if this is not the primary reason for the behavior, it is at least a reason.
Suppose that the enum instead comes from a library which your project depends on. In the version you compile against, ONE
and TWO
are the only options. However, you may end up running against a later version (through OSGi or other solutions) that has added another value THREE
. If THREE
gets passed to fooToInt
, it will reach the end of your method, and nothing will have been returned (or thrown). Oops.
This is rather unpleasant to discover at runtime, so you are forced to make a choice as to how it will be handled, even if it actually seems impossible at compile time. Some cases, like the one in your example, could probably be detected and allowed to compile, and other cases could have been handled differently (e.g. an implicit throw
), but on the list of all things that could be done to improve Java, I wouldn't put that at the top.
Since you did not write default, the compiler added it automatically at the next line after switch block. At that point, the compiler "notice" that there is no return point from the method and gives you that error.
I've taken you example and changed but added throw of RuntimeException after the switch, like this:
public class Example {
enum Foo { ONE, TWO }
int fooToInt(Foo foo) {
if (foo == null) {
throw new NullPointerException();
}
switch (foo) {
case ONE: return 1;
case TWO: return 2;
}
throw new RuntimeException("Should not have gotten here");
}
public static void main(String[] args) {
}
}
I've compiled the class and used javap -c Example.class to see the actual bytecode (see below). Notice the "default: 52" which was added by the javac. It leads to the block section after the switch case, and there, I've thrown RuntimeException which overwrite the need for return.
Compiled from "Example.java"
public class com.mprv.automation.jenkins.Example {
public com.mprv.automation.jenkins.Example();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
int fooToInt(com.mprv.automation.jenkins.Example$Foo);
Code:
0: aload_1
1: ifnonnull 12
4: new #2 // class java/lang/NullPointerException
7: dup
8: invokespecial #3 // Method java/lang/NullPointerException."<init>":()V
11: athrow
12: getstatic #4 // Field com/mprv/automation/jenkins/Example$1.$SwitchMap$com$mprv$automation$jenkins$Example$Foo:[I
15: aload_1
16: invokevirtual #5 // Method com/mprv/automation/jenkins/Example$Foo.ordinal:()I
19: iaload
20: lookupswitch { // 2
1: 48
2: 50
default: 52
}
48: iconst_1
49: ireturn
50: iconst_2
51: ireturn
52: new #6 // class java/lang/RuntimeException
55: dup
56: ldc #7 // String Should not have gotten here
58: invokespecial #8 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
61: athrow
public static void main(java.lang.String[]);
Code:
0: return
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With