ODER-Operator im Schalterfall?

Lesezeit: 6 Minuten

Benutzeravatar von Droidman
Droidenmann

Nehmen wir einen einfachen Switch-Fall, der so aussieht:

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

Ich frage mich, warum es nicht erlaubt ist, die zu verwenden || Operator? Wie

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

Das switch-case Konstrukt ist ziemlich ähnlich zu einem if-else -Anweisung können Sie den OR-Operator in einer verwenden if jedoch. Was sind die Hintergründe für a switch-case diesen Operator nicht akzeptieren?

  • @OliCharlesworth ja. Überprüfen Sie meinen Kommentar auf die Antwort von Arshajii

    – Droidenmann

    23. August 2013 um 22:45 Uhr

  • arshajii scheint darauf keine Antwort zu haben…

    – Dennis Meng

    23. August 2013 um 22:46 Uhr

  • || ist im Wesentlichen die Standardoperation einer case-Anweisung in Abwesenheit von break.

    – Trevor Freemann

    23. August 2013 um 22:50 Uhr

  • Stellen Sie sich das so vor: Wenn switch die gleiche Fähigkeit wie if-else hätte, warum brauchen wir dann beide? Es wird überflüssig!! Die Idee von switch besteht darin, die Lesbarkeit zu verbessern, anstatt Spaghetti-Code mit mehreren if-else-Blöcken zu schreiben. Aufgrund seiner Einfachheit bietet Switch wohl auch eine etwas bessere Leistung.

    – SerotoninChase

    23. August 2013 um 22:54 Uhr

  • Die Ada-Sprache tut genau das, wonach Sie fragen – würden Sie sagen when Some_Value | Some_Other_Value => in einem case Aussage. Aber die Sprache verwendet nicht | als Operator, daher kann diese Syntax auf keinen Fall mehrdeutig sein. Mit || für diesen Zweck in C (Java usw.) würde die Syntax mehrdeutig machen, und es ist keine gute Idee, verrückte Regeln mit Ausnahmen zu haben (wie || bedeutet in einem Ausdruck eine Sache, außer dass es in einem anderen Kontext etwas anderes bedeutet. ..).

    – ajb

    23. August 2013 um 23:28 Uhr

Kumpel, mach das so

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

Dies ist dasselbe wie die Verwendung des OR-Operators zwischen zwei Werten. Aus diesem Grund gibt es den Operator in switch case nicht

  • Hey @BalusC diese Antwort hat mir tatsächlich bei meiner Bewerbung geholfen, also schlage ich vor, diese “Antwort” zu behalten

    – Tasse

    20. März 2019 um 18:44 Uhr

  • Fantastische Lösung.

    – Stephan Bakkelund Valois

    7. November 2020 um 16:43 Uhr

Benutzeravatar von Rohit Jain
Rohit Jain

Was sind die Hintergründe dafür, dass ein Switch-Fall diesen Operator nicht akzeptiert?

Da case erfordert einen konstanten Ausdruck als Wert. Und seit ein || Ausdruck ist keine Kompilierzeitkonstante, es ist nicht erlaubt.

Aus JLS-Abschnitt 14.11:

Die Schalterbezeichnung sollte folgende Syntax haben:

SwitchLabel:
case KonstanterAusdruck :
Fall EnumConstantName :
Ursprünglich :


Unter der Haube:

Der Grund dafür, nur konstante Ausdrücke mit Fällen zuzulassen, kann aus dem verstanden werden JVM Spec Abschnitt 3.10 – Kompilieren von Schaltern:

Die Kompilierung von Switch-Anweisungen verwendet die Tischschalter und Nachschlageschalter Anweisungen. Der Tabellenumschaltbefehl wird verwendet, wenn die Fälle des Umschaltens effizient als Indizes in einer Tabelle von Zieloffsets dargestellt werden können. Das Standardziel des Schalters wird verwendet, wenn der Wert des Ausdrucks des Schalters außerhalb des Bereichs gültiger Indizes liegt.

Also, für die Fälle, die von verwendet werden tableswitch Als Index in die Tabelle der Ziel-Offsets sollte der Wert des Falls zur Kompilierzeit bekannt sein. Das ist nur möglich, wenn der Fallwert ein konstanter Ausdruck ist. Und || Der Ausdruck wird zur Laufzeit ausgewertet, und der Wert ist nur zu diesem Zeitpunkt verfügbar.

Aus demselben JVM-Abschnitt das Folgende switch-case:

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

wird kompiliert zu:

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

Also, wenn die case value ist kein konstanter Ausdruck, der Compiler kann ihn nicht in die Tabelle der Anweisungszeiger indizieren, indem er verwendet tableswitch Anweisung.

  • Ich habe das Gefühl, dass der Fragesteller das weiß, sich aber wundert, warum diese Einschränkung überhaupt besteht.

    – AdamSpurgin

    23. August 2013 um 22:45 Uhr

  • @Maver1ck Wahrscheinlich, weil es nicht nötig ist, da Sie einfach den Fall-Through verwenden können. Obwohl dies in Scala erlaubt ist (und auf ein absurdes Extrem getrieben wird).

    – arshajii

    23. August 2013 um 22:47 Uhr


  • @Maver1ck Es kann hilfreich sein, die Frage so zu ändern, dass Sie wissen, wie Sie dies innerhalb der angegebenen Syntax tun sollen, aber Sie fragen sich nur, warum dies keine akzeptable Alternative ist

    – Dennis Meng

    23. August 2013 um 22:47 Uhr


  • @Maver1ck “Da ein Ausdruck keine Kompilierzeitkonstante ist, ist er nicht zulässig.” Aus diesem Grund kann es in vielen Fällen durch eine einfachere Compileroptimierung schneller ausgeführt werden. Es ist schneller als if-Anweisungen aufgrund von Tricks und Magie auf niedrigem Niveau.

    – progrenhard

    23. August 2013 um 22:48 Uhr


  • @Maver1ck: Es lohnt sich auch, darauf hinzuweisen R.id.foo || R.id.bar bedeutet nichts, in keinem Kontext (vorausgesetzt foo und bar sind nicht boolean).

    – Oliver Charlesworth

    23. August 2013 um 23:08 Uhr

Benutzeravatar von Hilaj
Hilaj

Sie können || nicht verwenden Operatoren zwischen 2 Fall. Sie können jedoch mehrere Groß-/Kleinschreibungswerte verwenden, ohne einen Umbruch zwischen ihnen zu verwenden. Das Programm springt dann zum entsprechenden Fall und sucht dann nach auszuführendem Code, bis es einen “Bruch” findet. Infolgedessen teilen sich diese Fälle denselben Code.

switch(value) 
{ 
    case 0: 
    case 1: 
        // do stuff for if case 0 || case 1 
        break; 
    // other cases 
    default: 
        break; 
}

  • So habe ich mir das noch nie vorgestellt, interessanter Ansatz.

    – serraosays

    11. April 2019 um 3:18 Uhr

  • Oder Sie können auch so verwenden, Fall 0, 1: //falls Fall 0 || 1

    – Hilaj

    29. Mai 2019 um 10:46 Uhr


  • Dies sollte die richtige Antwort sein. Sogar Android Studio zeigt einen Vorschlag für eine Zusammenführung mit doppeltem Zweig an

    – Libin Thomas

    20. September 2019 um 9:34 Uhr

  • Java 14 hat eine neue switch-Anweisung mit einer Syntax wie case 0, 1 -> ... die zu einem Ausdruck ausgewertet, einen Codeblock ausgeführt oder ausgelöst werden kann.

    – Benutzer904963

    24. November 2021 um 22:17 Uhr

Ich kenne keinen besten Ansatz, aber ich mache es so

case 'E':
case 'e':
   System.exit(0);
   break;

Switch ist nicht dasselbe wie if-else-if.

Switch wird verwendet, wenn es einen Ausdruck gibt, der zu einem Wert ausgewertet wird, und dieser Wert einer der vordefinierten Wertesätze sein kann. Wenn Sie zur Laufzeit mehrere boolesche / Vergleichsoperationen ausführen müssen, muss if-else-if verwendet werden.

Benutzeravatar von Dave Lee
David Lee

Du kannst es immer noch so machen.

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

Benutzeravatar von Breimer
Breimer

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;


    }
}

Dies funktioniert gut für Sprachen, die Gehäuse unterstützen

1431160cookie-checkODER-Operator im Schalterfall?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy