Armen Michaeli
Armen Michaeli

Reputation: 9140

how to return with if and switch statements in function body

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

Answers (7)

pap
pap

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

Xavi López
Xavi López

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

Azodious
Azodious

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

Frerich Raabe
Frerich Raabe

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

Stephen O'Flynn
Stephen O'Flynn

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

Vikdor
Vikdor

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

duffymo
duffymo

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

Related Questions