1050 Stimmen

Warum kann ich die switch-Anweisung nicht für einen String verwenden?

Wird diese Funktion in einer späteren Java-Version enthalten sein?

Kann mir jemand erklären, warum ich das nicht tun kann, d.h. die technische Art und Weise, wie Java's switch Aussage funktioniert?

203 Stimmen

Es ist in SE 7. 16 Jahre nach seinem Antrag. download.oracle.com/javase/tutorial/java/nutsandbolts/

88 Stimmen

Sun war ehrlich in ihrer Bewertung: "Don't hold your breath." lol, bugs.sun.com/bugdatabase/view_bug.do?bug_id=1223179

3 Stimmen

@raffian Ich glaube, das liegt daran, dass sie zweimal 'seufzte'. Sie waren auch ein bisschen spät dran mit ihrer Antwort, nach fast 10 Jahren. Vielleicht hat sie damals Lunchpakete für ihre Enkelkinder gepackt.

1025voto

erickson Punkte 256579

Switch-Anweisungen mit String Fälle wurden umgesetzt in Java SE 7 , mindestens 16 Jahre nachdem sie zum ersten Mal angefordert wurden. Ein klarer Grund für die Verzögerung wurde nicht genannt, aber er hatte wahrscheinlich mit der Leistung zu tun.

Implementierung in JDK 7

Die Funktion wurde jetzt in folgende Bereiche implementiert javac mit einem "De-Sugaring"-Prozess; eine saubere, hochsprachliche Syntax mit String Konstanten in case Deklarationen zur Kompilierzeit zu komplexerem Code nach einem Muster erweitert wird. Der resultierende Code verwendet JVM-Anweisungen, die schon immer existierten.

A switch avec String Fälle werden bei der Kompilierung in zwei Schalter übersetzt. Der erste ordnet jede Zeichenfolge einer eindeutigen Ganzzahl zu - ihrer Position im ursprünglichen Schalter. Dies geschieht, indem zunächst der Hash-Code des Labels eingeschaltet wird. Der entsprechende Fall ist ein if Anweisung, die die Gleichheit von Zeichenketten prüft; wenn es Kollisionen auf dem Hash gibt, ist der Test eine kaskadierende if-else-if . Der zweite Schalter spiegelt den des ursprünglichen Quellcodes wider, ersetzt aber die Groß-/Kleinschreibung durch die entsprechenden Positionen. Dieser zweistufige Prozess macht es einfach, die Flusskontrolle des ursprünglichen Schalters zu erhalten.

Schalter in der JVM

Für mehr technische Tiefe über switch können Sie in der JVM-Spezifikation nachschlagen, wo die Zusammenstellung von switch-Anweisungen beschrieben wird. Kurz gesagt gibt es zwei verschiedene JVM-Befehle, die für einen Schalter verwendet werden können, je nach der Sparsamkeit der von den Fällen verwendeten Konstanten. Beide hängen von der Verwendung ganzzahliger Konstanten für jeden Fall ab, um effizient ausgeführt werden zu können.

Wenn die Konstanten dicht sind, werden sie als Index (nach Abzug des niedrigsten Wertes) in einer Tabelle mit Anweisungszeigern verwendet - der tableswitch Anweisung.

Wenn die Konstanten spärlich sind, wird eine binäre Suche nach dem richtigen Fall durchgeführt - die lookupswitch Anweisung.

Bei der Entzuckerung eines switch auf String Objekten, werden wahrscheinlich beide Anweisungen verwendet. Die Website lookupswitch eignet sich für den ersten Schalter auf Hash-Codes, um die ursprüngliche Position des Gehäuses zu finden. Die sich daraus ergebende Ordnungszahl ist eine natürliche Passform für eine tableswitch .

Bei beiden Anweisungen müssen die jedem Fall zugewiesenen Ganzzahlkonstanten zur Kompilierzeit sortiert werden. Zur Laufzeit, während die O(1) Leistung von tableswitch erscheint im Allgemeinen besser als die O(log(n)) Leistung von lookupswitch Wenn die Tabelle so dicht ist, dass der Zeit- und Raumaufwand gerechtfertigt ist, muss eine Analyse durchgeführt werden. Bill Venners schrieb ein großartiger Artikel in dem dies ausführlicher behandelt wird, zusammen mit einem Blick unter die Haube auf andere Java-Flusssteuerungsanweisungen.

Vor JDK 7

Vor JDK 7, enum könnte eine Annäherung an eine String -basierten Schalter. Dieser verwendet die Statik valueOf Methode, die vom Compiler bei jeder enum Art. Zum Beispiel:

Pill p = Pill.valueOf(str);
switch(p) {
  case RED:  pop();  break;
  case BLUE: push(); break;
}

128voto

JeeBee Punkte 17329

Wenn Sie eine Stelle in Ihrem Code haben, an der Sie eine Zeichenkette einschalten können, dann ist es vielleicht besser, die Zeichenkette zu einer Aufzählung der möglichen Werte umzuformulieren, die Sie einschalten können. Natürlich schränken Sie die möglichen Werte von Strings auf die in der Aufzählung enthaltenen ein, was erwünscht sein kann oder auch nicht.

Natürlich könnte Ihre Aufzählung einen Eintrag für "other" und eine fromString(String)-Methode haben, dann könnten Sie

ValueEnum enumval = ValueEnum.fromString(myString);
switch (enumval) {
   case MILK: lap(); break;
   case WATER: sip(); break;
   case BEER: quaff(); break;
   case OTHER: 
   default: dance(); break;
}

91voto

Im Folgenden finden Sie ein vollständiges Beispiel, das auf dem Beitrag von JeeBee basiert, wobei Java Enum's anstelle einer benutzerdefinierten Methode verwendet werden.

Beachten Sie, dass Sie in Java SE 7 und höher stattdessen ein String-Objekt im Ausdruck der switch-Anweisung verwenden können.

public class Main {

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) {

      String current = args[0];
      Days currentDay = Days.valueOf(current.toUpperCase());

      switch (currentDay) {
          case MONDAY:
          case TUESDAY:
          case WEDNESDAY:
              System.out.println("boring");
              break;
          case THURSDAY:
              System.out.println("getting better");
          case FRIDAY:
          case SATURDAY:
          case SUNDAY:
              System.out.println("much better");
              break;

      }
  }

  public enum Days {

    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
  }
}

27voto

James Curran Punkte 98228

Schalter, die auf Ganzzahlen basieren, können zu sehr effizientem Code optimiert werden. Schalter, die auf anderen Datentypen basieren, können nur in einer Reihe von if()-Anweisungen kompiliert werden.

Aus diesem Grund sind in C und C++ nur Schalter für Integer-Typen zulässig, da dies bei anderen Typen sinnlos ist.

Die Entwickler von C# haben entschieden, dass der Stil wichtig ist, auch wenn er keine Vorteile bringt.

Die Entwickler von Java dachten offenbar wie die Entwickler von C.

20voto

Ein Beispiel für direkte String Die Nutzung seit 1.7 kann ebenfalls angezeigt werden:

public static void main(String[] args) {

    switch (args[0]) {
        case "Monday":
        case "Tuesday":
        case "Wednesday":
            System.out.println("boring");
            break;
        case "Thursday":
            System.out.println("getting better");
        case "Friday":
        case "Saturday":
        case "Sunday":
            System.out.println("much better");
            break;
    }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X