views:

719

answers:

14

I appreciate that anything that can be done done by a switch statment can be done by an if else statement.

But are there stylistic rules for when one should use the switch rather than if else statment.

+3  A: 

You use a switch statement when you are switching on different values of primitive / enum / wrapper types. (And not all primitive / wrapper types, just the supported ones - byte, short, char, int).

If/else handles the rest.

For instance, it is more aesthetically pleasing to say:

int i = getValueOfI();
switch (i) {
  case 1:
    // do something
    break;
  case 2:
    // do something
    break;

etc.

than

if (i == 1) {

} else if (i == 2) {

}...

for a large number of cases. But you can't switch on Strings, or function values, or complex conditions, so if you need to do any of that then you're stuck with if/else.

danben
I'm not 100% convinced its aesthetically more pleasing - sort of depends what you are used to. The problem with the switch is that it is so easy to forget the break statement.
Dan
@Dan: I made it a habit of always typing the `case` and `break` in pairs. That way I never forget them. But I agree that it's not too nice. Though there are probably not many people arguing on that front :-)
Joey
Agreed at least with the if-else you have the syntax to help you - maybe the default in a switch should have been break after a case was matched.
Dan
+1  A: 

first of all, the switch statement has to be useable. If the switch is based on the value of a variable, then it can be used. If it is based on a complex AND/OR/NOT boolean expression that varies for each condition, then you can't use it at all.

That being said, if it is applicable, and there are at least 2 cases, then I use the switch. It is more easily extendible, easier to read and check.

Larry Watanabe
A: 

if you have too many conditions to check of a similar type u can go for switch.

GK
A: 

As with other languages such as C or C++, switch statements are useful when you want to compare a given variable with a list of possible values and perform an action depending on these values. It is terser than if else statements.

Otávio Décio
+8  A: 

Well, switch feels "lighter" in many cases than an if/else if ladder, in my opinion. Basically you don't have that much syntax with braces and parentheses in the way of your code. That being said, switch has the <subjective>nasty</subjective> habit of inheriting C's <subjective>braindead</subjective> syntax. Which means break and only a single scope for variables (unless you introduce new blocks).

Still, the compiler is able to optimize switch statements into a lookup table and perform compile-time checking for literals when dealing with enumerations, so I'd suggest that it's usually preferrable to use switch over if/else if if you're dealing with numeric or enum types.

Joey
FWIW, strings in switch statements is in JDK7
basszero
@basszero: Is this final? Last I know it was still to be decided yet.
BalusC
+3  A: 

I use switch statements for enums, it is more readable that a if else if else if statements. However, you should try to avoid such checks in a OO design.

bertolami
+1  A: 

There are two factors for me:

Readability and whether you want to decide something using ranges of values or conditions (in switch statements you can only use a single integer or enumerated value).

Alex
Agreed, anything requiring *ranges* of values needs an `if` statement.
Loadmaster
A: 

Personnally, i use to find both constructs a little too procedural. Although it may considered as OO extermism, I use to use a Map containing instances of an internal interface for each cases of the if. It allows better code isolation, i think. However, to trully reply your question, I only use switchs when I have cases that really overlap (the, I don't use break statements). Unfortunatly, it's really not a maintainable code block.

Riduidel
A: 

Switch has two relevant disadvantages:

  • it is limited to primitive types and enums
  • you have to remember "break", what could lead to not so obvious bugs

Often switch is a sign for poor OO design, because you'd better use polymorphism.

The only possible advantage of switch is, that it is more readable. But is

switch (i) {
  case 1:
    // do something
    break;
  case 2:
    // do something
    break;
}

more readable than this:

if (i == 1)
  //do something
else if (i == 2)
  // do something else

I'd say: no! And you wouldn't have the disadvantages of switch.

My suggestion: Try to avoid switch.

deamon
You probably wouldn't do a switch for just two cases anyhow. Rather than avoiding switch, learning how to use it effectively is a better idea, which is exactly what the question is asking.
Atømix
+4  A: 

Switch has one advantage when it comes to clarity:

switch (i) {
  case 1:
    // do something
    break;
  case 2:
  case 4:
    // do something
    break;
  case 5:
    // do something
    break;
}

If the code for 2 and 4 are identical, it may be more clear than:

if ( i == 1 ) {
  // do something
}
if ( (i == 2) || (i == 4) ) {
  // do something
}
id ( (i == 5 ) {
  // do something
}

It's also easier for you ( or another programmer ) to split out the 2 and 4 cases.

Atømix
A: 

Switch and enums.

If the enum value you are testing can legitimately be null for any reason, putting it into switch statement will generate a NullPointerException. Without looking at the byte code it's kind of baffling that it would do so.

The explanation: enums are syntactic sugar introduced in 1.5. Switch statement still works with good-ole ints, but the values the it uses are ordinals assigned to enum. In order to get the ordinal, the enum value MUST be non-null.

if statement, on the other hand, would be happy to accept null for an enum value and just fail the test without NPE.

Alexander Pogrebnyak
A: 

Maybe a bit offtopic, but if I answered just the question in the title, then I would say that you shouldn't use switch in all situations where cases represent states of some object. State pattern is much prettier solution in those cases.

Roman
A: 

I'd suggest the simple rule:

Always use a switch when you have at least 2 options to differentiate between, the data type is usable for a switch and all options have constant values.

In most cases switch is faster than a if/else cascade, makes the intention of the code clearer and the oh so bad forgotten break dilemma is not worse than huge if/else cascades that accidently breaks in between because somebody forgot a else.

Java VMs actually support two different sorts of switch, the tableswitch and the lookupswitch instruction. The tableswitch gets generated by the compiler if all case constants lie in a narrow range, otherwise it generates a lookupswitch. For large switch statements with many cases the tableswitch is more efficient than the lookupswitch that is usually implemented by some form of binary search.

x4u
+1  A: 

I've always found that the java switch statement is not as powerful as I need. In his last release lambdaj implements it with a smart use of closure and Hamcrest matcher.

For example the lambdaj Switcher allows to implement a strategy pattern. Supposing you have to switch between three sorting algorithm based on some characteristic of the list to be sorted. In particular let's assume we have an algorithm specialized for Strings:

public List<String> sortStrings(List<String> list) {
    // a sort algorithm suitable for Strings
}

another one that works well with small lists having no more than 100 items:

public List<T> sortSmallList(List<T> list) {
    // a sort algorithm suitable for no more than 100 items
}

and more general purpose one:

public List<String> sort(List<String> list) {
    // a generic sort algorithm
}

Given these 3 sorting methods it is possible to create a strategy that chooses the most suitable of them in the following declarative way:

Switcher<List<T>> sortStrategy = new Switcher<List<T>>()
    .addCase(having(on(List.class).get(0), instanceOf(String.class))), 
        new Closure() {{ of(this).sortStrings(var(List.class)); }})
    .addCase(having(on(List.class).size(), lessThan(100))), 
        new Closure() {{ of(this).sortSmallList(var(List.class)); }})
    .setDefault(new Closure() {{ of(this).sort(var(List.class)); }});

and sort a list using the best available algorithm by invoking the Switcher:

List<T> sortedList = sortStrategy.exec(list, list);
Mario Fusco
+1: This looks cool. It amazes me that Java's switch statement is still so weak: you can't even switch on an Integer. Scala's match expression is far more powerful. Heck, Cobol (19)85's EVALUATE statement is substantially more useful.
Jim Ferrans