OR operator in switch-case?
Asked Answered
F

10

69

Let's take a simple switch-case that looks like:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.someValue :
        case R.id.someOtherValue:
            // do stuff
            break;
    }
}

I wonder why it is not allowed to use the || operator? Like

switch (v.getId()) {
    case R.id.someValue || R.id.someOtherValue:
        // do stuff
        break;
}

The switch-case construct is pretty similar to an if-else statement, you can use the OR operator in an if however. What are the backgrounds for a switch-case to not accept this operator?

Firebrat answered 23/8, 2013 at 22:41 Comment(6)
@OliCharlesworth yep. Check my comment for arshajii's answerFirebrat
arshajii doesn't seem to have an answer...June
|| is essentially the default operation of a case statement in the absence of break.Brain
Think about it this way - If switch had the same capability as if-else then why do we need both? It'll be redundant!! The idea of switch is to improve readability as opposed to writing spaghetti code with multiple if else blocks. Arguably switch also gives slightly a better performance due to its simplicity.Weintrob
The Ada language does the exact sort of thing you're asking about--you'd say when Some_Value | Some_Other_Value => in a case statement. But the language doesn't use | as an operator, so there's no way this syntax could be ambiguous. Using || for this purpose in C (Java, etc.) would make the syntax ambiguous, and it's not a good idea to have funky rules with exceptions (like || means one thing in an expression except that it means something different in a different context...).Plasterboard
Because it's redundant?Latvina
S
62

What are the backgrounds for a switch-case to not accept this operator?

Because case requires constant expression as its value. And since an || expression is not a compile time constant, it is not allowed.

From JLS Section 14.11:

Switch label should have following syntax:

SwitchLabel:
case ConstantExpression :
case EnumConstantName :
default :


Under the hood:

The reason behind allowing just constant expression with cases can be understood from the JVM Spec Section 3.10 - Compiling Switches:

Compilation of switch statements uses the tableswitch and lookupswitch instructions. The tableswitch instruction is used when the cases of the switch can be efficiently represented as indices into a table of target offsets. The default target of the switch is used if the value of the expression of the switch falls outside the range of valid indices.

So, for the cases label to be used by tableswitch as a index into the table of target offsets, the value of the case should be known at compile time. That is only possible if the case value is a constant expression. And || expression will be evaluated at runtime, and the value will only be available at that time.

From the same JVM section, the following switch-case:

switch (i) {
    case 0:  return  0;
    case 1:  return  1;
    case 2:  return  2;
    default: return -1;
}

is compiled to:

0   iload_1             // Push local variable 1 (argument i)
1   tableswitch 0 to 2: // Valid indices are 0 through 2  (NOTICE This instruction?)
      0: 28             // If i is 0, continue at 28
      1: 30             // If i is 1, continue at 30
      2: 32             // If i is 2, continue at 32
      default:34        // Otherwise, continue at 34
28  iconst_0            // i was 0; push int constant 0...
29  ireturn             // ...and return it
30  iconst_1            // i was 1; push int constant 1...
31  ireturn             // ...and return it
32  iconst_2            // i was 2; push int constant 2...
33  ireturn             // ...and return it
34  iconst_m1           // otherwise push int constant -1...
35  ireturn             // ...and return it

So, if the case value is not a constant expressions, compiler won't be able to index it into the table of instruction pointers, using tableswitch instruction.

Squaw answered 23/8, 2013 at 22:42 Comment(6)
I get the feeling the asker knows this, but is wondering why this restriction is in place to begin with.Lima
@Maver1ck Probably because there's no need for it, since you can just use the fall-through. Although, this is allowed (and taken to an absurd extreme) in Scala.Lidstone
@Maver1ck It might be helpful then to modify the question to state that you know how you're supposed to do it within the given syntax, but you're just wondering why this isn't an acceptable alternativeJune
@Maver1ck "since an expression is not a compile time constant, it is not allowed." because of this it can execute faster through easier compiler optimization in many cases. It's faster than if statements because of low level tricks and magic.Hear
@Maver1ck: It's also worth pointing out that R.id.foo || R.id.bar doesn't mean anything, in any context (assuming foo and bar aren't boolean).Gretagretal
A compiler could easily interpret case 0 || 1 (or some variation of that) as two constants in a lookup table. For example, Java 14 now has the syntax case 0, 1 -> ... followed by an expression, a code block, or a throw.Manamanacle
U
124

dude do like this

    case R.id.someValue :
    case R.id.someOtherValue :
       //do stuff

This is same as using OR operator between two values Because of this case operator isn't there in switch case

Utoaztecan answered 23/8, 2013 at 22:45 Comment(2)
hey @BalusC this answer actually helped me with my application so I suggest to keep this "answer"Actin
Updated answer is here: Can you connect two cases of a switch statement using a commaPsychotic
S
62

What are the backgrounds for a switch-case to not accept this operator?

Because case requires constant expression as its value. And since an || expression is not a compile time constant, it is not allowed.

From JLS Section 14.11:

Switch label should have following syntax:

SwitchLabel:
case ConstantExpression :
case EnumConstantName :
default :


Under the hood:

The reason behind allowing just constant expression with cases can be understood from the JVM Spec Section 3.10 - Compiling Switches:

Compilation of switch statements uses the tableswitch and lookupswitch instructions. The tableswitch instruction is used when the cases of the switch can be efficiently represented as indices into a table of target offsets. The default target of the switch is used if the value of the expression of the switch falls outside the range of valid indices.

So, for the cases label to be used by tableswitch as a index into the table of target offsets, the value of the case should be known at compile time. That is only possible if the case value is a constant expression. And || expression will be evaluated at runtime, and the value will only be available at that time.

From the same JVM section, the following switch-case:

switch (i) {
    case 0:  return  0;
    case 1:  return  1;
    case 2:  return  2;
    default: return -1;
}

is compiled to:

0   iload_1             // Push local variable 1 (argument i)
1   tableswitch 0 to 2: // Valid indices are 0 through 2  (NOTICE This instruction?)
      0: 28             // If i is 0, continue at 28
      1: 30             // If i is 1, continue at 30
      2: 32             // If i is 2, continue at 32
      default:34        // Otherwise, continue at 34
28  iconst_0            // i was 0; push int constant 0...
29  ireturn             // ...and return it
30  iconst_1            // i was 1; push int constant 1...
31  ireturn             // ...and return it
32  iconst_2            // i was 2; push int constant 2...
33  ireturn             // ...and return it
34  iconst_m1           // otherwise push int constant -1...
35  ireturn             // ...and return it

So, if the case value is not a constant expressions, compiler won't be able to index it into the table of instruction pointers, using tableswitch instruction.

Squaw answered 23/8, 2013 at 22:42 Comment(6)
I get the feeling the asker knows this, but is wondering why this restriction is in place to begin with.Lima
@Maver1ck Probably because there's no need for it, since you can just use the fall-through. Although, this is allowed (and taken to an absurd extreme) in Scala.Lidstone
@Maver1ck It might be helpful then to modify the question to state that you know how you're supposed to do it within the given syntax, but you're just wondering why this isn't an acceptable alternativeJune
@Maver1ck "since an expression is not a compile time constant, it is not allowed." because of this it can execute faster through easier compiler optimization in many cases. It's faster than if statements because of low level tricks and magic.Hear
@Maver1ck: It's also worth pointing out that R.id.foo || R.id.bar doesn't mean anything, in any context (assuming foo and bar aren't boolean).Gretagretal
A compiler could easily interpret case 0 || 1 (or some variation of that) as two constants in a lookup table. For example, Java 14 now has the syntax case 0, 1 -> ... followed by an expression, a code block, or a throw.Manamanacle
G
49

You cannot use || operators in between 2 case. But you can use multiple case values without using a break between them. The program will then jump to the respective case and then it will look for code to execute until it finds a "break". As a result these cases will share the same code.

switch(value) 
{ 
    case 0: 
    case 1: 
        // do stuff for if case 0 || case 1 
        break; 
    // other cases 
    default: 
        break; 
}
Gavrilla answered 26/8, 2018 at 5:54 Comment(4)
Never thought of it quite like this, interesting way to do it.Octennial
Or you can use like this also, case 0, 1: //if the case 0 || 1Gavrilla
This should be the correct answer. even android studio will show a suggestion to a merge with duplicate branchYiyid
Java 14 has a new switch statement with syntax like case 0, 1 -> ... which can evaluate to an expression, execute a code block, or throw.Manamanacle
B
5

I do not know a best approach but I do it as

case 'E':
case 'e':
   System.exit(0);
   break;
Beisel answered 21/4, 2021 at 4:29 Comment(0)
K
1

Switch is not same as if-else-if.

Switch is used when there is one expression that gets evaluated to a value and that value can be one of predefined set of values. If you need to perform multiple boolean / comparions operations run-time then if-else-if needs to be used.

Knitted answered 23/8, 2013 at 23:8 Comment(0)
F
1

Since Java 12 and on it is possible to have multiple values in cases:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.someValue, R.id.someOtherValue:
            // do stuff
            break;
    }
}

OR

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.someValue, R.id.someOtherValue -> {/* do stuff */}
    }
}
Femininity answered 3/2, 2023 at 13:8 Comment(0)
L
0

You can still do it like this.

switch (v.getId()) {
    case R.id.someValue: case R.id.someOtherValue:
        // do stuff
        break;
}
Lissner answered 1/8, 2022 at 18:10 Comment(0)
R
0

Try using enhanced switch

switch (value)
{
    case R.id.someValue, R.id.someOtherValue -> // do stuff
}
Revolutionize answered 7/2 at 8:47 Comment(0)
H
-1
foreach (array('one', 'two', 'three') as $v) {
    switch ($v) {
        case (function ($v) {
            if ($v == 'two') return $v;
            return 'one';
        })($v):
            echo "$v min \n";
            break;


    }
}

this works fine for languages supporting enclosures

Helio answered 18/11, 2017 at 13:14 Comment(0)
E
-1

helps in some cases.

switch(true){
 case a == b: break;
 case a == 2 || a == 3: break;
 default: break;
} 
Embosser answered 15/5, 2022 at 19:7 Comment(2)
Please write your answer in English, as Stack Overflow is an English-only site.Nickname
While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.Nickname

© 2022 - 2024 — McMap. All rights reserved.