39

Why doesn't the switch expression allow long, float, double or boolean values in Java? why is only int (and those that are automatoically promoted to int) allowed?

Joachim Sauer
  • 291,719
  • 55
  • 540
  • 600
saravanan
  • 5,129
  • 7
  • 43
  • 52
  • 13
    switch exists for boolean, it is called `if ... else` – Nicolas Feb 28 '11 at 12:18
  • 1
    Due to the precision problem , i think they are not allowed. – Dead Programmer Feb 28 '11 at 12:25
  • @saravanan I didn't like any of the answer here: have you seen this post: [**Question about switch{} case in C?**](http://stackoverflow.com/questions/5179822/question-about-switch-case-in-c) – Grijesh Chauhan Mar 03 '13 at 08:31
  • Closely related to, but not quite a duplicate of http://stackoverflow.com/questions/2676210/why-cant-your-switch-statement-data-type-be-long-java – Raedwald Aug 12 '14 at 11:50

4 Answers4

40

Float and double would be awkward to use reliably even if they were possible - don't forget that performing exact equality matches on float/double is usually a bad idea anyway, due to the nature of the representation.

For Boolean values, why not just use if to start with?

I can't remember ever wanting to switch on any of these types, to be honest. Do you have a particular use case in mind?

Jon Skeet
  • 1,335,956
  • 823
  • 8,931
  • 9,049
  • 2
    I could see a use case for `float` or `double` for version information. `1.1` will always be `1.1` if you don't do any calculations. Even Java uses this trick to display version information sometimes. But I guess we'll have to byte the bullit and compare against an actual object instance representing a `Version` - or use `String` comparison from Java 7 onwards of course. – Maarten Bodewes May 12 '14 at 16:26
  • 5
    @owlstead: 1.1 isn't a valid `float` or `double` number. You can have a literal which will convert to the *closest* `float` or `double`, but neither can precisely-represent 1.1. Did you actually mean version 1.100000000000000088817841970012523233890533447265625 (`double`) or version 1.10000002384185791015625 (`float`)? – Jon Skeet May 12 '14 at 16:28
  • Would that matter? I presume that if you parse a String then you will get either of the numbers. But I can see where it could go wrong if you mix floats and doubles. So probably the Java devs where right to leave it out. Anyway, since 1.7 there is the `String` switch which does not have these issues. Using a `double` or `float` for a version is a hack anyway. – Maarten Bodewes May 12 '14 at 16:56
  • 3
    @owlstead: It matters because it's fundamentally an inappropriate type to use. Also, what do you do for more specific versions? If you want 1.1.1 for example? That clearly can't be represented as a `float` or `double`. Even with just major/minor, you have odd things - version 1.10 (the 11th minor version in major version 1) would be equal to 1.1. How is that useful? Using `float` or `double` for a version number is just *wrong* in my view. – Jon Skeet May 12 '14 at 16:59
  • I agree, but I see it used in quite a few API's - even Oracle ones. And switching on version nubmers is certainly a *use case*. But as said, it's a hack, and hacks should be avoided - I would consider it wrong as well. So maybe this is an additional reason to avoid the hack. There must be a Java puzzler somewhere in this :) – Maarten Bodewes May 12 '14 at 17:03
  • 1
    @owlstead: I would certainly *hate* to see a language feature introduced because it would help in situations where an API had been badly designed. Ick, ick, ick. – Jon Skeet May 12 '14 at 17:04
  • @JonSkeet, I prefer switch over if-else because in switch, a jump table is created. So switch has a performance edge and it works slightly faster than if-else. – Confuse Mar 22 '15 at 14:56
  • @Aryan: I focus on correctness first - and floating point equality is hardly ever appropriate, so it makes sense that it isn't available in switch statements. It's not even clear that a jump table would be sensibly possible for a float... – Jon Skeet Mar 22 '15 at 15:16
  • @JonSkeet, actually I was talking about general switch working, not specifically focusing on floating point variables. – Confuse Mar 22 '15 at 15:25
  • @Aryan: Then it's not clear how it's related to this question/answer. And I wouldn't even prefer switch "in general" - I prefer whichever is most readable for the situation. – Jon Skeet Mar 22 '15 at 15:31
  • I was talking about this question which you asked in your answer - "I can't remember ever wanting to switch on any of these types, to be honest. Do you have a particular use case in mind?". – Confuse Mar 22 '15 at 15:32
  • @Aryan: Well that's specifically for float/double/boolean, as per the original question. Which of them were your referring to? – Jon Skeet Mar 22 '15 at 15:47
  • I was referring to other types too like int/string etc. I am sorry but I didn't notice that you were talking specifically about float/double/boolean. – Confuse Mar 22 '15 at 15:51
  • An example were you would want to switch case a boolean will be if you want to Switch on ranges of integers. For example: `int x = 20; switch(true){ case x >0 && x <10 : ...; case x >10 && x <20: ... ; case x >20 && x <30: ... ; ....}` . This is really useful. – Yaki Klein Apr 23 '15 at 17:26
  • @YakiKlein: That's moving way beyond just "switching on different types" though - that's now switching on *expressions* rather than constants. That's not what the question was about. – Jon Skeet Apr 23 '15 at 17:31
  • that's true. I did not think of it that way. – Yaki Klein Apr 23 '15 at 19:18
  • @JonSkeet, why are they supported in C#? – Shimmy Weitzhandler Oct 31 '18 at 21:17
10

You can use enum in a switch statement and Java 7 will add String AFAIK. The switch statement comes from C where only int's were allowed and implementing other types is more complicated.

Floating point numbers are not a good candiates for switch as exact comparison is often broken by rounding errors. e.g. 0.11 - 0.1 == 0.01 is false.

switch on boolean is not much use as a plain if statement would be simpler

if(a) {

} else { 

}

would not be simpler with

switch(a) {
  case true:

     break;
  case false:

     break;
}

BTW: I would use switch(long) if it were available, but its not. Its a rare use case for me any way.

Peter Lawrey
  • 513,304
  • 74
  • 731
  • 1,106
3

For float and double float and double I'd assume they have omitted it for the same reasons as why it's a bad idea to compare them using ==.

For boolean, it may simply be because it would correspond to an if statement anyway. Remember that you can only have constants in the case-expressions, so the cases would always correspond to if (someBool) and if (!someBool).

For long I don't have an explanation. Seems to me that such feature perhaps should have been included when designing the language.

aioobe
  • 399,198
  • 105
  • 792
  • 807
  • @aiodbe But would it be worth changing the language to support `switch` on `long`. That's a surprising amount of work for spectacularly little gain. (I guess why there wasn't `switch` on `long` in 1.0 is that it wouldn't fit with the existing pair of `switch` ops, so would either have to add two more pointless ops or provide a separate mechanism for compiling this case. And JDK 1.00 needed to ship to Netscape in six weeks.) – Tom Hawtin - tackline Feb 28 '11 at 12:31
  • Ah, I agree completely. I guess I was trying to say "seems like a reasonable good idea to include". I know that the current ops are tied to `ints` so yes, it would probably involve a change in the bytecode set which is a huge thing to begin with. Updated the answer slighly. – aioobe Feb 28 '11 at 12:56
1

Usually switch-case structure is used when executing some operations based on a state variable. There an int has more than enough options. Boolean has only two so a normal if is usually good enough. Doubles and floats aren't really that accurate to be used in this fashion.

Frankly I can't imagine a use case for this stuff, did you have some practical problem in mind with this question?

Mikko Wilkman
  • 1,455
  • 10
  • 8