Reputation: 9140
I have a Java code with the following pattern:
enum Foo
{
ORANGE, APPLE, BANANA
}
Foo bar()
{
switch(calcValue())
{
case "orange": return ORANGE;
case "apple": return APPLE;
case "banana": return BANANA;
}
}
The design of calcValue
method ensures it never returns anything else than the three strings that the switch statement checks. If it would not be able to return either of the three strings, it throws an exception. This implies that the missing default
keyword may be unnecessary and the default switch behavior is never triggered, hence default
is omitted. However, Java naturally (and rightfully so, in general) complains that bar
must (always) return a value. I was thinking to throw an exception as default, but as mentioned calcValue
throws one already. I am primarily after a simple and efficient (involving least runtime checks and code) design to solve this little problem - I don't want to throw two exceptions, and calcValue
is not under my control, so I cannot do anything with it.
I hope I have explained myself well here, if not, I will do my best to try to clarify. In essence, this is about designing methods with value where switch defaults are known to not apply. That may also apply to if-then-else-if-then-else-...-then-else
statement patterns.
Upvotes: 0
Views: 155
Reputation: 27614
A common pattern is to have the enum know how to translate itself properly
public enum Foo {
BANANA("banana"),
ORANGE("orange"),
APPLE("apple");
private String calculationCode;
private Foo(String calculationCode) {
this.calculationCode=calculationCode;
}
public static Foo byCalculationCode(String code) {
for (Foo foo : values()) {
if (foo.calculationCode.equals(code)) {
return foo;
}
}
throw new NoSuchElementException("Unknown code:" + code);
}
Upvotes: 1
Reputation: 27880
Not directly answering the question, but maybe it would simplify things to use Enum.valueOf()
. If calcValue()
is guaranteed to return one of those three values, you could just do:
enum Foo { ORANGE, APPLE, BANANA }
Foo bar() { return Foo.valueOf(calcValue().toUpperCase()); }
And delegate the decision to Enum.valueOf
, which, by the way, throws an IllegalArgumentException
if there's no such element.
Upvotes: 1
Reputation: 13882
You said
calcValue is not under my control
Then, you should not depend on it that it'll always throw
an exception.
You should add default
to your switch
construct and should throw exception if control reaches there.
Another point is that your bar()
method should be complete in itself.
You are trying to make it tightly coupled with calcValue()
. The signature contract of Bar()
says that it'll always return a Foo
but instead of doing that you are depending on calcValue()
to implement the contract; and that's wrong.
Upvotes: 1
Reputation: 94389
You wrote
The design of calcValue method ensures it never returns anything else than the three strings that the switch statement checks.
However, this contract is not expressed by the signature of calcValue
; it just returns a string and the type checker of Java has no way to know that only some strings are possible. I'd consider this a flaw in the API of the calcValue
function.
The bottom line is that Java is correct - you do lack a default
case, since your assumption about the inner workings of calcValue
is not enforced by the type system, so it may change at any point without the compiler noticing.
Upvotes: 2
Reputation: 2329
It's asking for good reason; since you don't control calcValue(), you should have code to handle future changes.
But, if you want to continue as above, change the last case to default so that it always returns "BANANA" in the absence of ORANGE or APPLE.
Upvotes: 1
Reputation: 24134
Even though calcValue()
throws an error for the default case, that is a logical conclusion and Java compiler wouldn't understand that and so is complaining about a code path without a return. You HAVE to throw an exception from this method as well for the default case.
Upvotes: 1
Reputation: 308878
Long if/then/else and switch statements are a bad sign, in my opinion. I prefer writing in an object-oriented style whenever I can.
Like using a Map, passing in the key, and returning the value.
Your simple example could and should be an enum.
Upvotes: 1