Warum funktioniert switch aber nicht if/else?

anghenfil

Mitglied
Hallo,
ich habe eine Frage bezüglich der folgenden Quelltexte. Wieso funktioniert das gewünschte per switch, nicht aber per if/else?

Mit switch:
Java:
        String decision;
        Scanner sc = new Scanner(System.in);
      
        TD.input_question("Editor oder Spiel starten?");
        decision = sc.next();
        decision = decision.toLowerCase(); //Making input lower case
        sc.close();
        switch(decision){
        case "editor":
            Editor.editor();
            break;
        case "spiel":
            createnew = UserManager.checkUserData(); //Check if User file already exists
            if(createnew){ //If new user needed
                UserManager.userCreation(); //Start User Creation
                UserManager.loadUser(); //Load  User data (from User Creation) and start game
            }else if(createnew == false){
                UserManager.loadUser(); //Load User data and starts game
            }
            break;
        default:
            main(args);
        }

Mit if/else:
Java:
        String decision;
        Scanner sc = new Scanner(System.in);
      
        TD.input_question("Editor oder Spiel starten?");
        decision = sc.next();
        decision = decision.toLowerCase(); //Making input lower case
        if(decision == "editor"){
            Editor.editor();
        }else if(decision == "spiel"){
            createnew = UserManager.checkUserData(); //Check if User file already exists
            if(createnew){ //If new user needed
                UserManager.userCreation(); //Start User Creation
                UserManager.loadUser(); //Load  User data (from User Creation) and start game
            }else if(createnew == false){
                UserManager.loadUser(); //Load User data and starts game
            }
        }else{
            System.out.println(decision);
            main(args);
        }

Wenn ich das ganze mit if/else mache, erkennt er die Eingabe nicht und springt zu else.

Vielen Dank im Vorraus,
Grüße anghenfil
 
Zuletzt bearbeitet von einem Moderator:
String ist ein Referenzdatentyp.
Wenn du ein == verwendest vergleichst du die Speicheradresse der beiden Objekte, nicht aber deren Inhalt.
Java:
    String a = "a";
    String b = "b";

    if(a == b) {
        // wird nicht ausgeführt.
    }

    if(a.equals(b)) {
        // heurika, wird ausgeführt.
    }

Wenn du eine Variable deklarierst reservierst du dafür Speicher. In diesem Beispiel wird mit "String a" gesagt das du Speicher benötigst. Die Variable "a" zeigt jetzt auf eine Adresse im Speicher. An der Adresse wird dein eigentlicher Wert abgelegt. Bei == wird dann nur geschaut ob die beiden Adressen gleich sind... das kann aber nicht der Fall sein. == würde nur funktionieren wenn a == a ist.
 
Statt equal muss es natürlich equals heissen. Und das man "Strings [...] mit Equal und Switch (vergleicht)" ist Quatsch.

"Strings vergleicht man mit equals, und switch weiß das."


Wieso heurika ? a und b sind ja nicht equals
Sehr weit hergeholt, aber da der Kontext nicht ersichtlich ist, wäre es zumindest möglich, dass der Inhalt von a und/oder b in der Zwischenzeit von anderer Stelle geändert wurde. 😉

Bezüglich der Frage des TEs fällt mir nur ein, dass eine Sammlung von Standard-Antworten sehr nützlich wäre. Statt auf "Antwort erstellen" wählt man einfach eine Antwort aus der Liste aus. Spart jedem Zeit und Nerven
 
Machen wir doch einen kleinen Test?:
Java:
class Test {
    static String a = "a", b = "b", c = "c";
    static String d1 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
    public static void main(String[] args) throws InterruptedException {
        String d2 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
        int[] array = new int[3];
        for (int j = 0; j < 10; j++) {
            String d3 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
            ExecutorService es = Executors.newFixedThreadPool(3);
            es.submit(() -> {
                String d4 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
                Random r = new Random();
                switch (r.nextInt(4)) {
                    case 0:
                        a = d1;
                        break;
                    case 1:
                        a = d2;
                        break;
                    case 2:
                        a = d3;
                        break;
                    case 3:
                        a = d4;
                        break;
                    default:
                        throw new AssertionError();
                }
            });
            es.submit(() -> {
                String d4 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
                Random r = new Random();
                switch (r.nextInt(4)) {
                    case 0:
                        b = d1;
                        break;
                    case 1:
                        b = d2;
                        break;
                    case 2:
                        b = d3;
                        break;
                    case 3:
                        b = d4;
                        break;
                    default:
                        throw new AssertionError();
                }
            });
            es.submit(() -> {
                String d4 = new String(new char[]{'h', 'a', 'l', 'l', 'o'});
                Random r = new Random();
                switch (r.nextInt(4)) {
                    case 0:
                        c = d1;
                        break;
                    case 1:
                        c = d2;
                        break;
                    case 2:
                        c = d3;
                        break;
                    case 3:
                        c = d4;
                        break;
                    default:
                        throw new AssertionError();
                }
            });
            es.shutdown();
            es.awaitTermination(5, TimeUnit.SECONDS);
            if (a == b) {
                array[0]++;
            }
            if (a == c) {
                array[1]++;
            }
            if (b == c) {
                array[2]++;
            }
        }
        System.out.println("a==b " + array[0] + " Mal a==c " + array[1] + " Mal b==c " + array[2] + " Mal von " + 10);
    }
}


Code:
a==b 2 Mal a==c 3 Mal b==c 4 Mal von 10
Was ich damit andeuten möchte, "der String pool 'kann nicht' immer greifen".
 
a) Strings vergleicht man nicht mit ==, das war die Antwort auf den Fehler,
b) dass eine Diskussion entstanden ist, ist mehr so on top,
c) Pommes schmecken auch nicht ohne Majo 😀

Ich hab mittlerweile festgestellt, dass bei mehreren Threads (innerhalb einer Schleife) ein lokaler String der Form String s = new String(new char[]{'h', 'i'}); nicht in den String pool wandert. Demzufolge ist ein gemeinsamer String pool mehrerer Threads (in dem Fall) wohl zu aufwändig. Bei nur einem (nicht wiederverwendeten) Thread funktioniert's. Da hat sich viel geg. früher in der Realisierung der VM geändert.
Aaaber, ihr habt's vielleicht schon bemerkt: ICH bewege mich da im Vagen / Unwissenheit. 😀
Also wenn es jemand anders erklären kann, nur zu. Ich lern gerne was dazu. 😀
Leider muss ich feststellen, dass mein Beispiel auch nicht "minimal" ist.
 
Zuletzt bearbeitet von einem Moderator:
@DerWissende HIER ist die Erklärung warum deine Strings nicht "interned" werden, denn du baust die String zur Laufzeit mit String::new. StringPool hat nichts mit Threads zu tun sondern mit Packages und Classes.

Grundsätzlich werden nur String Literale in den Threadpool gelegt und können manuell mit String#intern interened werden. Dann klappts auch mit dem Vergleichsoperator, aber der StringPool wird zu 99,9% der Fälle nicht vom Garbage Collector besucht und bläst den HeapSpace unnötig auf.
 
new String( wandert in den String pool, ich hab's ausprobiert, nur eben nicht in allen Fällen. Scheint, als hätte sich einiges geändert in letzter Zeit.
 

Zurück
Oben