Warum kann ich nicht mit switch-Anweisung auf eine Zeichenfolge?
Ist diese Funktionalität gehen, um in einer späteren Java-version?
Kann mir jemand erklären, warum ich dies nicht tun, als in die technische Möglichkeit Java switch
- Anweisung funktioniert?
Es ist in der SE 7. 16 Jahre, nachdem Sie nach Anfrage. download.oracle.com/javase/tutorial/java/nutsandbolts/...
Sonne war ehrlich in Ihrer Einschätzung:
Ich denke, es ist, weil Sie 'seufz' ed zweimal. Sie waren ein wenig zu spät zu Antworten, auch nach fast 10 Jahren. Sie war vielleicht die Verpackung lunch-Boxen für Ihre Enkel dann.
Sonne war ehrlich in Ihrer Einschätzung:
"Don't hold your breath."
lol, bugs.sun.com/bugdatabase/view_bug.do?bug_id=1223179Ich denke, es ist, weil Sie 'seufz' ed zweimal. Sie waren ein wenig zu spät zu Antworten, auch nach fast 10 Jahren. Sie war vielleicht die Verpackung lunch-Boxen für Ihre Enkel dann.
InformationsquelleAutor Alex Beardsley | 2008-12-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Switch-Anweisungen mit
String
Fällen umgesetzt worden Java SE 7, die mindestens 16 Jahre nachdem Sie wurden zuerst gebeten. Einen klaren Grund für die Verzögerung war nicht vorgesehen, aber wahrscheinlich hatte mit Leistung zu tun.Implementierung in JDK 7
Das feature wurde nun umgesetzt in
javac
mit einem "de-sugaring" - Prozess; einem sauberen, high-level-syntax mitString
Konstanten incase
Erklärungen erweitert wird zur compile-Zeit in komplexeren code nach einem Muster. Der resultierende code verwendet JVM-Instruktionen, die schon immer existiert haben.Einen
switch
mitString
Fällen ist übersetzt in zwei switches während der Kompilierung. Die erste ordnet jedem string einen eindeutigen integer—seine position in der original-Schalter. Dies geschieht, indem Sie zuerst die Umschaltung auf den hash-code des Etiketts. Der entsprechende Fall ist eineif
Aussage, dass die tests auf string-Gleichheit; wenn es Kollisionen auf den hash, der test ist ein cascadingif-else-if
. Der zweite Schalter Spiegel, die in den ursprünglichen Quellcode, sondern ersetzt den case-Bezeichnungen mit den entsprechenden Positionen. Dieser zwei-Schritt-Prozess macht es einfach, um die Erhaltung der Fluss-Steuerung von der original-Schalter.Schalter in der JVM
Weitere technische Tiefe auf
switch
finden Sie in der JVM-Spezifikation, wobei die Zusammenstellung von switch-Anweisungen beschrieben wird. Kurz gesagt, es gibt zwei verschiedene JVM-Instruktionen, die verwendet werden können, für einen Schalter, je nach der sparsity der Konstanten, die von den Fällen. Beide hängen mit integer-Konstanten für die jeweils zur Ausführung effizient.Wenn die Konstanten dichten, Sie werden als ein index (nach Abzug der niedrigste Wert) in einer Tabelle der Anweisung Zeiger—die
tableswitch
Unterricht.Wenn die Konstanten sind spärlich, eine binäre Suche nach der richtigen groß - /Kleinschreibung durchgeführt wird—die
lookupswitch
Unterricht.In der de-sugaring eine
switch
aufString
Objekte, die beide Anweisungen verwendet werden könnten. Dielookupswitch
geeignet ist für den ersten Schalter auf hash-codes zu finden, die original-position der Fall ist. Die daraus resultierende Ordnungszahl ist eine Natürliche fit für einetableswitch
.Beide Befehle erfordern die integer-Konstanten zugeordnet jedem Fall sortiert werden zur compile-Zeit. Zur Laufzeit, während der
O(1)
Leistungtableswitch
erscheint in der Regel besser als dieO(log(n))
Leistunglookupswitch
erfordert einige Analyse, um zu bestimmen, ob die Tabelle ist dicht genug, um zu rechtfertigen, das Raum–Zeit-Abwägung. Bill Venners schrieb ein toller Artikel, deckt diese im detail, zusammen mit einer unter-die-Haube den Blick auf andere Java-flow-Kontrolle Anleitung.Vor JDK 7
Vor JDK 7,
enum
könnte die Annäherung an eineString
-basiert wechseln. Dies nutzt die statischevalueOf
Methode generiert der compiler auf jedenenum
geben. Zum Beispiel:Eine if-elseif-elseif-elseif-else-könnte schneller sein, aber würde ich nehmen, die sauberer code 99 mal von 100. Streicher, Unveränderbarkeit, cache-Ihre hash-code, also "computing" der hash ist schnell. Man müsste den Profil-code, um zu bestimmen, welche Vorteile es gibt.
Der Grund gegen das hinzufügen switch(String) ist, dass es würde nicht erfüllen die performance-Garantien erwartet von switch () - statements. Sie wollen sich nicht "täuschen" - Entwickler. Ehrlich gesagt, ich glaube nicht, Sie sollten Garantie für die Leistung der switch() zu beginnen.
Wenn Sie nur
Pill
einige Maßnahmen zu ergreifen, basierend aufstr
ich würde behaupten wenn-sonst ist vorzuziehen, da es Ihnen erlaubt zu handhabenstr
Werte außerhalb des Bereichs liegen ROTE,BLAUE, ohne zu fangen, eine Ausnahme vonvalueOf
oder suchen Sie manuell nach einem match gegen den Namen jeder Enumerationstyp, die fügt nur unnötigen overhead. Meiner Erfahrung nach ist es nur sinnvoll zu verwendenvalueOf
zur Umwandlung in eine enumeration, wenn eine typesafe Darstellung der String-Wert wurde später benötigt.Ich Frage mich, ob Compiler machen jede Anstrengung, um zu testen, ob es irgendein paar von zahlen (x,y), für die die Werte
(hash >> x) & ((1<<y)-1)
würden ergeben unterschiedliche Werte für jede saite, derenhashCode
ist anders, und(1<<y)
ist weniger als das doppelte der Anzahl der Saiten (oder zumindest nicht viel größer).InformationsquelleAutor erickson
Wenn Sie eine Stelle im code, wo man Umschalten kann auf einen String, dann kann es besser sein, zu der die Umgestaltung der Zeichenkette eine Aufzählung der möglichen Werte, die Sie einblenden können. Natürlich, Sie beschränken die möglichen Werte der Zeichenfolgen, die Sie haben können, zu denen in der Aufzählung, die möglicherweise oder möglicherweise nicht gewünscht.
Natürlich Ihre Aufzählung könnte haben einen Eintrag für die 'anderen', und einen fromString(String) - Methode, dann könnten Sie
Vereinbaren Sie mit JeeBee, wenn Sie einschalten strings müssen wahrscheinlich ein enum . Der string in der Regel stellt so etwas gehen, um eine Schnittstelle (Benutzer oder anderes), oder nicht, kann sich in Zukunft ändern, also besser ersetzen Sie es mit enums
Siehe xefer.com/2006/12/switchonstring für eine schöne write-up von dieser Methode.
Der write-up hat einen großen Fehler. Es fängt alle Ausnahmen, anstatt diejenigen, die tatsächlich geworfen werden, von der methode.
InformationsquelleAutor JeeBee
Die folgenden ist ein vollständiges Beispiel, basierend auf JeeBee ' s post, die mit java-enum statt der Verwendung einer eigenen Methode.
Beachten Sie, dass in Java SE 7 und höher können Sie die Verwendung eines String-Objekts in der switch-Anweisung ist Ausdruck statt.
InformationsquelleAutor Thulani Chivandikwa
Schalter auf der Basis von Ganzzahlen optimiert werden können, um sehr effiziente code. Schalter auf der Basis von anderen Daten-Typ kann nur kompiliert werden, um eine Reihe von if () - statements.
Deshalb C & C++ erlauben nur den Schalter auf integer-Typen, da es sinnlos war mit anderen Arten.
Die Designer von C# entschieden, dass der Stil war wichtig, auch wenn es keinen Vorteil gab.
Sich die Designer von Java anscheinend dachte, wie die Designer von C.
Ja, und dies ist die Sache, die ich nicht verstehe. Haben Sie Angst, hashing Objekte, auf die Dauer zu teuer?
tatsächlich, mit ein wenig Mühe auf den Teil des Compilers, es ist überhaupt nicht teuer, denn wenn die Menge der strings bekannt ist, ist es ziemlich einfach zu generieren eine perfekte hash (das ist nicht getan .NET, obwohl, wahrscheinlich lohnt der Aufwand nicht, entweder).
Rudolph - Während hashing String (aufgrund der unveränderlichen Natur) scheint eine Lösung für dieses problem, das Sie haben sich daran zu erinnern, dass alle nicht-final-Objekte können Ihre Hash-Funktionen außer Kraft gesetzt. Dies macht es schwierig, zur compile-Zeit zur Gewährleistung der Konsistenz in einem switch.
Sie können auch konstruieren Sie einen DFA, entspricht der Zeichenfolge (wie regelmäßige Ausdruck-Motoren zu tun). Möglicherweise sogar effizienter als Hash.
InformationsquelleAutor James Curran
James Curran kurz und bündig sagt: "Schalter auf der Basis von Ganzzahlen optimiert werden können, um sehr effiziente code. Schalter auf der Basis von anderen Daten-Typ kann nur kompiliert werden, um eine Reihe von if () - statements. Aus diesem Grund ist C & C++ erlauben nur den Schalter auf integer-Typen, da es sinnlos war, mit anderen Typen".
Meiner Meinung nach, und es ist nur, dass, ist, dass, sobald Sie beginnen, Umstellung auf nicht-primitive, die Sie brauchen, um darüber nachzudenken, "gleich" versus "==". Erstens vergleicht zwei strings kann eine ziemlich langwierige Prozedur, hinzufügen, um die performance-Probleme, die oben erwähnt werden. Zweitens, wenn es Wechsel bei strings gibt es Nachfrage für das einschalten der strings ignorieren Fall einschalten strings unter Berücksichtigung/ignorieren Gebietsschema Umschalten auf strings basiert auf der regex.... Ich würde Zustimmen, eine Entscheidung, die viel Zeit gespart, die für die Sprache der Entwickler auf Kosten einer kleinen Menge von Zeit für die Programmierer.
matched
undnot matched
. (Nicht berücksichtigt Dinge wie [namens] Gruppen/etc. obwohl.)docs.oracle.com/javase/7/docs/technotes/guides/language/... states: Der Java-compiler erzeugt in der Regel effizienter bytecode von switch-Anweisungen, die die Verwendung von String-Objekten als von verketteten if-then-else-Anweisungen.
InformationsquelleAutor DJClayworth
Beispiel für eine direkte
String
Nutzung seit 1.7 kann gezeigt werden:InformationsquelleAutor Gunnar Forsgren - Mobimation
Neben dem oben genannten guten Argumente, ich will hinzufügen, dass viele Menschen heute sehen
switch
als eine veraltete Rest des Verfahrensrechts Vergangenheit von Java (zurück zu C-Zeiten).Ich nicht ganz teilen diese Meinung, ich denke
switch
kann seine Nützlichkeit in einigen Fällen, zumindest aufgrund seiner Schnelligkeit, und jedenfalls ist es besser als einige Reihe von cascading numerischeelse if
sah ich in einiger code...Aber in der Tat, es lohnt sich auf den Fall, wo Sie brauchen, ein Schalter, und sehen, ob es nicht ersetzt werden kann durch etwas mehr OO. Zum Beispiel enums in Java 1.5+, vielleicht HashTable oder eine andere Sammlung (irgendwann bereue ich das wir nicht haben (anonyme) Funktionen wie erste Klasse Bürger, wie in Lua—, die nicht über Schalter oder JavaScript) oder auch Polymorphie.
Ja, natürlich. Aber möchtest du noch einen Kommentar an alle Antworten aus den letzten zehn Jahren zu sagen, die Welt, die wir haben können, wenn wir es aktualisieren auf neuere Versionen von Java? 😀
InformationsquelleAutor PhiLho
Wenn Sie nicht mit JDK7 oder höher verwenden, können Sie
hashCode()
zu simulieren. DaString.hashCode()
in der Regel gibt Werte für unterschiedliche Zeichenfolgen und gibt immer die gleichen Werte für die gleichen Saiten sind, ist es ziemlich zuverlässig (Verschiedene strings kann erzeugen, die denselben hash-code wie @Lii erwähnt in einem Kommentar, wie"FB"
und"Ea"
) Siehe Dokumentation.So, der code würde wie folgt Aussehen:
So, Sie sind technisch Wechsel auf eine
int
.Alternativ dazu könnten Sie den folgenden code verwenden:
Vielen Dank für diesen Hinweis! Es ist unwahrscheinlich, aber ich würde nicht Vertrauen, dass es funktioniert. "FB" und "Ea" haben den gleichen hashcode, so ist es nicht unmöglich, eine Kollision zu finden. Der zweite code ist wahrscheinlich zuverlässiger.
Ich bin überrascht, diese kompiliert, als
case
Aussagen musste, dachte ich, immer Konstante Werte, und dieString.hashCode()
ist nicht so (auch wenn in der Praxis die Berechnung hat sich nie geändert zwischen JVMs).Hm interessant, ich habe nie aufgehört, zu beobachten. Aber ja,
case
- Anweisung Werte nicht bestimmbar sind zur compile-Zeit, so dass es funktioniert fein.InformationsquelleAutor HyperNeutrino
Seit Jahren haben wir mit einer(n open source) Präprozessor.
Vorgefertigte Dateien mit Namen Foo.jpp und verarbeitet in Foo.java mit einem ant-script.
Vorteil ist, es ist verarbeitet in Java, läuft auf 1.0 (obwohl in der Regel wir nur unterstützt, zurück auf 1.4). Auch war es viel einfacher, dies zu tun (viele string-switches) im Vergleich zu fudging es mit enums oder andere workarounds - code war viel einfacher zu Lesen, zu warten und zu verstehen. IIRC (kann keine Statistiken oder technische Argumentation an dieser Stelle) es war auch schneller, als die Natur Java Entsprechungen.
Nachteile sind Sie nicht die Bearbeitung von Java, so ist es ein bisschen mehr workflow (Bearbeiten, verarbeiten, kompilieren/testen) sowie ein IDE-einen link zurück zu Java, das ist ein wenig verworren (der Schalter wird eine Reihe von if/else-Logik-Schritte) und die switch-case-Reihenfolge nicht beibehalten wird.
Ich würde nicht empfehlen es für 1.7+, aber es ist nützlich, wenn Sie wollen Java-Programm, dass Ziele früher JVMs (da Joe public hat selten den neuesten installiert).
Können Sie es aus dem SVN oder durchsuchen Sie die code online. Sie müssen EBuild zu bauen es wie es ist.
InformationsquelleAutor Charles Goodwin
Anderen Antworten gesagt haben, dies wurde Hinzugefügt, der in Java 7 und gegeben Abhilfen für frühere Versionen. Diese Antwort versucht eine Antwort auf die "warum"
Java war eine Reaktion auf die über-Komplexität von C++. Es wurde entwickelt, um eine einfache, saubere Sprache.
String noch ein bisschen spezieller Fall der Umgang in der Sprache, aber es scheint mir klar, dass die Designer haben versucht, zu halten, die Menge der speziellen Gehäuse und syntaktischen Zucker auf ein minimum.
einschalten strings ist Recht Komplex unter der Haube, da die Saiten nicht einfach primitive Typen. Es war nicht ein gemeinsames Merkmal in der Zeit Java wurde entworfen und passt nicht wirklich gut mit dem minimalistischen design. Gerade als Sie beschlossen hatte, nicht zu spezielle Fall == für strings, es wäre (und ist) ein bisschen seltsam für Fall, zu arbeiten, wo == nicht.
Zwischen 1.0 und 1.4 die Sprache selbst blieb ziemlich genau die selben. Die meisten der Verbesserungen von Java wurden auf der Bibliothek-Seite.
All das änderte sich mit Java 5 wurde die Sprache wesentlich erweitert. Weitere Erweiterungen folgten in den Versionen 7 und 8. Ich erwarte, dass diese Veränderung der Haltung war bedingt durch den Aufstieg von C#
Es war ein großer Fehler, nicht, um diese Funktion zu implementieren, alles andere ist eine billige Ausrede, Java verloren viele Nutzer im Laufe der Jahre wegen der mangelnden Fortschritte und die Sturheit der Designer nicht für die Weiterentwicklung der Sprache. Zum Glück haben Sie völlig die Richtung gewechselt und die Einstellung nach JDK7
InformationsquelleAutor plugwash
Nicht sehr schön, aber hier ist eine weitere Möglichkeit für Java 6 und Balg:
InformationsquelleAutor Conete Cristian
Ist es ein Kinderspiel in Groovy; ich einbetten der groovy-jar, und erstellen Sie eine
groovy
utility-Klasse zu tun, all diese Dinge und mehr das finde ich ärgerlich zu tun, die in Java (da bin ich stecken mit Hilfe von Java 6, die in der enterprise.)Denn dies ist eine java-Frage und groovigem Antwort ist off-topic und nutzlos Stecker.
Selbst in konservativen großen SW-Häusern Groovy wird zusammen mit Java. JVM gibt eine Sprache, die agnostischen Umgebung mehr als eine Sprache, zu mischen, und verwenden Sie die wichtigsten Programmier-Paradigma für die Lösung. Also vielleicht jetzt sollte ich noch hinzufügen eines snippets in Clojure zu sammeln, mehr downvotes 🙂 ...
Auch, wie sieht der syntax arbeiten? Ich vermute, Groovy ist eine andere Programmiersprache...? Sorry. Ich weiß nicht, etwas über Groovy.
InformationsquelleAutor Alex Punnen
Wenn Sie intellij auch anschauen:
Datei -> Projekt-Struktur -> Projekt
Datei -> Projekt-Struktur -> Module
Wenn Sie mehrere Module stellen Sie sicher, dass Sie die richtige Sprache Ebene in der Registerkarte Modul.
Nicht sicher, wie Ihre Antwort ist relevant für die Frage. Er fragte, warum ein string switch-Anweisungen wie folgt nicht zur Verfügung: String mystring = "etwas"; switch (mystring) { case "etwas" sysout("got"); . . }
InformationsquelleAutor botenvouwer
InformationsquelleAutor Issac Balaji