34

How does Java's switch statement work under the hood? How does it compare the value of the variable being used, to those given in the case parts? Does it use == or .equals(), or is it something else entirely?

I'm mainly interested in the pre 1.7 versions.

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
  • What version of Java are you interested in? In 1.7 switch works with Strings too. – Andrew Logvinov Aug 18 '12 at 16:07
  • Before 1.7, `switch` only works with enums and primitives, for which `==` and `.equals` are the same thing. – Louis Wasserman Aug 18 '12 at 16:14
  • @LouisWasserman and boxed primitives so the question still makes sense. – assylias Aug 18 '12 at 16:16
  • Huh. I figured it didn't have a special case for boxed primitives; it just did the autounboxing and used the primitive switch. – Louis Wasserman Aug 18 '12 at 16:17
  • 2
    Some googling would have turned up [this](http://stackoverflow.com/questions/2086529/what-is-the-relative-performance-difference-of-if-else-versus-switch-statement-i) and [this](http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11) – Tony R Aug 18 '12 at 16:18
  • @LouisWasserman The JLS mentions the case of boxed primitives and indeed says that they are unboxed. – assylias Aug 18 '12 at 16:19
  • @TonyR True. However, I needed a somewhat more specific answer. Like João, with an example etc. – Raghav Sood Aug 18 '12 at 16:20

7 Answers7

24

Neither. it uses the lookupswitch JVM instruction, which is essentially a table lookup. Take a look at the bytecode of the following example:

public static void main(String... args) {
  switch (1) {
  case 1:
    break;
  case 2:
    break;
  }
}

public static void main(java.lang.String[]);
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   iconst_1
   1:   lookupswitch{ //2
                1: 28;
                2: 31;
                default: 31 }
   28:  goto    31
   31:  return
user207421
  • 305,947
  • 44
  • 307
  • 483
João Silva
  • 89,303
  • 29
  • 152
  • 158
  • 8
    This is not really true. It uses a lookupswitch when there are gaps in your cases (more than one gap, or a single gap that has a value difference greater than 1). Otherwise, it uses a tableswitch which is more effecient. You can find more information here https://www.artima.com/underthehood/flowP.html – searchengine27 Aug 24 '15 at 18:21
  • the lookupswitch link is dead and after reading the comment and the answer I am not sure which is more accurate. – rd22 Feb 17 '16 at 08:32
  • The link I gave is not dead, and explains switch statements accurately. But if you're still not convinced, compile a switch statement in various cases, and then look at the Java assembly to see for yourself. Eclipse will actually let you compile your Java, and then open up your .class file for reading, and you can see the Java assembly in your IDE. – searchengine27 Jun 01 '17 at 21:33
12

As you can see from this answer, Java switch (at least pre-1.7) does not always compile into == or .equals(). Instead, it uses table lookup. While this is a very small micro-optimization, when doing a great many comparisons, table lookup will almost always be faster.

Note that this is only used for switch statements that check against dense keys. For example, checking an enum value for all of its possibilities would probably yield this primary implementation (internally called tableswitch).

If checking against more sparsely-populated sets of keys, the JVM will use an alternative system, known as lookupswitch. It will instead simply compare various keys and values, doing essentially an optimized == comparison for each possibility. To illustrate these two methods, consider the following two switch statements:

switch (value1) {
case 0:
    a();
    break;
case 1:
    b();
    break;
case 2:
    c();
    break;
case 3:
    d();
    break;
}

switch (value2) {
case 0:
    a();
    break;
case 35:
    b();
    break;
case 103:
    c();
    break;
case 1001:
    d();
    break;
}

The first example would most likely use table lookup, while the other would (basically) use == comparison.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • I don't think this is a valid answer. The fact that one JVM uses that implementation does not enable us to conclude what switch does in general. – assylias Aug 18 '12 at 16:20
  • 1
    @assylias The question asks what `switch` does "under the hood." While it could have different implementations, claiming it uses `==` or `.equals()` would be just as false as this one. I think that understanding what the standard JVM uses at this time is a perfectly valid answer to such a question. – Alexis King Aug 18 '12 at 16:25
  • 1
    As you can see from the answer you linked, it *never* compiles into `==` or `.equals()`. And a table lookup is certainly *not* a 'microoptimization'. It is *O(1)* instead of *O(N)*. – user207421 Sep 07 '16 at 00:04
  • @EJP That’s technically accurate, but `lookupswitch` is semantically equivalent to `==`, even if the instructions are not technically the same. – Alexis King Sep 07 '16 at 00:11
8

Copied from here

In bytecode there are two forms of switch: tableswitch and lookupswitch. One assumes a dense set of keys, the other sparse. See the description of compiling switch in the JVM spec. For enums, the ordinal is found and then the code continues as the int case. I am not entirely sure how the proposed switch on String little feature in JDK7 will be implemented.

However, heavily used code is typically compiled in any sensible JVM. The optimiser is not entirely stupid. Don't worry about it, and follow the usual heuristics for optimisation.

You will find detailed answer over here

Community
  • 1
  • 1
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
1

1.Before the arrival of Java 7, it was "==", because we could use the integer and char for switch case, and as they were primitive, so it had to be "==".

2. From Java 7, String also was allowed in switch case, and String being an object, ".equals" is used.

I would like to add this... that "==" is used to compare the Object Reference Variable, not the Object itself. Using ".equals" we compare the objects.

Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
  • "equals and ==" depending on the type of the switched variable. Or are the int and chars converted to Integer, Character ? – Razvan Aug 18 '12 at 16:12
  • No - pre 1.7 Integer were allowed too for example. – assylias Aug 18 '12 at 16:14
  • So, I'll rephrase my comment: In java 7, considering that strings are allowed as the vars in the switch statement, the equality "operator" can be either "==" or ".equals" depending on the type of the switched var. Or, are the primitive types (int,char) boxed in their wrappers and only ".equals" is used, for uniformity. – Razvan Aug 18 '12 at 16:41
  • 1
    Both before and after the arrival of Java 7 it used `lookupswitch` and `tableswitch`, not `==` or `.equals()`. – user207421 Sep 07 '16 at 00:05
0

A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types (discussed in Enum Types), the String class, and a few special classes that wrap certain primitive types: Character, Byte, Short, and Integer. (Java 1.6)

While primitives are compared with ==, the switch method surely uses this kind of comparison in Java 1.6 (and earlier).

developer110
  • 508
  • 6
  • 9
-1

If using pre 1.7 Java I assume it uses

==

because for int you can't do equals for example and in case of enum, equals and == will return the same

EDIT

My assumption is wrong it uses a lookuptable, in bytecode it would like like:

 tableswitch
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Is there a canonical reference you could find? Is it possible at all for the switch case conditions to use a comparison that is neither ==, nor .equals()? – Raghav Sood Aug 18 '12 at 16:10
  • @RaghavSood: How would you compare two primitives, let alone objects, without some sort of comparison operator? I don't see how it would be possible to create a switch statement without any comparison operation. – Makoto Aug 18 '12 at 16:11
  • @Makoto I'm not saying there's no comparison operation going on. I'm asking if it is possible that some third, JVM only comparison can be used there that is not available in the API we have access to. – Raghav Sood Aug 18 '12 at 16:12
  • No - pre 1.7 Integer were allowed too for example. – assylias Aug 18 '12 at 16:13
  • You should edit out the incorrect part of your answer, and the assertion that `tableswitch` is 'not a lot faster than the usual if/else' is ridiculous. Consider a `switch` statement with hundreds of cases. It is *O(1)* instead of *O(N)*. – user207421 Sep 07 '16 at 00:06
-1

If you are using primitive types, such as integers, then java will use == to compare them If you are using Strings, then java will use the equals() method to test if the strings are equal. If you are using a switch statement with enums, then == and equals() are both the same, so it doesn't really matter which one is being used.

Alex Fischer
  • 545
  • 3
  • 11