开发者

When to use a switch statement in Java

I appreciate that anything that can be 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.


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 inherits C's syntax. That means you have 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 preferable to use switch over if/else if if you're dealing with numeric or enum types.


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
}
if ( (i == 5 ) {
  // do something
}

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


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.


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.


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.


I'd suggest the simple rule:

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

There are three good reasons. One, in most cases switch is faster than an if/else cascade. Two, it makes the intention of the code clearer. Three, the oh so bad forgotten break dilemma is a lesser evil than huge if/else cascades that accidentally break because somebody forgot an 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. The lookupswitch is usually implemented by some form of binary search.


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).


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.


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.


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.


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);


The answer depends on what exactly you are doing as well as the distribution of the choices.

If one condition is dominant then the if/then is appropriate.

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

If the conditions are evenly distributed the optimization in the compiler will provide a performance advantage. This performance difference becomes more pronounced as the number of possible choices increases.

switch (i) {
  case 1:
     // do something
     break;
  case 2:
     // do something else
     break;
  ....
  case N: 
     // do yet something else
     break;
  }

That said, if performance is NOT important go with which ever you approach you prefer as most readable (maintainable and easiest to write).

If on the other hand, if your code is in a hotspot where the performance IS important you should go with the switch.

For "extremely large" conditions, Mario's example of the lambdaj switcher is really cool and with care on the initialization will result in very high performance. It is very similar coding to what the optimizer is generating. I would define "extremely large" as when the number of options is large or complex enough to make it worth type all that in, and worth the support confusion to when a follow on developer is trying to go through the code. (Comment your code with why you have all that!).


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


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.


I agree with x4u's answer.

In addition there is another instance not mentioned, yet, where I think it is better to use if-else blocks rather than a switch: when additional conditions in each of the case blocks are tested with if blocks. I see this mixture all the time in existing code.

For example I just came across this code that has a switch on a string type and then checks a second string extension using an if in both case statements.

 public abstract class Temp {

    boolean valid;

    public Temp() {
        String type = getType();
        String extension = getFilenameExtension();
        switch(type) {
            case "Image File": {
                if(!".jpg".equals(extension) && !".png".equals(extension)) {
                    warnWrongImageFormat();
                    valid = false;
                }
                break;
            }
            case "Zip File": {
                if(!".zip".equals(extension)) {
                    warnWrongZipFormat();
                    valid = false;
                }
                break;
            }
            default: {
                valid = true;
                break;
            }
        }
    }

    abstract String getType();
    abstract String getFilenameExtension();
    abstract void warnWrongImageFormat();
    abstract void warnWrongZipFormat();
}

Instead it is much cleaner and less complex to reduce this to one if else

public abstract class Temp {

    boolean valid;

    public Temp() {
        String type = getType();
        String extension = getFilenameExtension();
        valid = true;
        if("Image File".equals(type) && !".jpg".equals(extension) && !".png".equals(extension)) {
            warnWrongImageFormat();
            valid = false;
        }
        else if("Zip File".equals(type) && !".zip".equals(extension)) {
            warnWrongZipFormat();
            valid = false;
        }
    }

    abstract String getType();
    abstract String getFilenameExtension();
    abstract void warnWrongImageFormat();
    abstract void warnWrongZipFormat();
}


Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing. An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, enumerated value, or String object. [The switch Statement - Oracle]


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜