Java Quiz

Mein Tipp

https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedList-java.util.List-java.lang.Class- an der richtigen Stelle?!

Korrekt das was auch die Lösung die ich gemeint habe.
Wie gesagt, im Normalfall sollte man das gar nicht brauchen, da man einfach niemals

List<String> names = new ArrayList<>();
List huh = names;

schreiben sollte. aber wenn man irgendeinen alten Legazy code hat, (wie z.B. ich der gescrieben wurde als ich in der Volksschule war) kann und dann irgendwo im Code eine ClassCastException bekommt, kann man damit sehr leicht den waren schuldigen finden.

LG

Ja, das Hauptproblem bei diesem Raw Types ist IIRC, dass sie die ganze Methode (oder sogar Klasse?) „vergiften“ - dort also dann wegen eines Raw Types die kompletten Generics-Checks über den Haufen geworfen werden. (Details müßte ich jetzt auch nachlesen, die Quintessenz ist „DON’T“, und die befolge ich üblicherweise :wink: )

Ein Quiz der anderen Art… welcher Songtitel wird hier gesucht?

public class You implements Comparable<Object> {

    @Override
    public int compareTo(Object nothing) {
        return -1;
    } 

 }

Der Song mit dem Titel You :blush: oder anders: Das (Bearbeitung: erste oder irgendein, Anmerkung: erstes, irgendeines oder bei mehreren sogar eine Runtime exception…) Object in der Collection, dessen Klasse des Typs You ist. :slight_smile:

?

Achso, das müssta nachsehen, Musik hab ich nicht studiert.

Oniken hat die Lösung gefunden “Nothing compare 2 U” von Sinead O’Connor.

Die englische Version:

Wirklich “wissen” kann man die Antwort kaum, aber …:

public class TestIntern
{
    public static void main(String[] args)
    {
        char[] c1 = { 'a', 'b', 'h', 'i' };
        String s1 = new String(c1);
        s1.intern();
        String s2 = "abhi";
        System.out.println(s1 == s2);

        char[] c2 = { 'j', 'a', 'v', 'a' };
        String sj1 = new String(c2);
        sj1.intern();
        String sj2 = "java";
        System.out.println(sj1 == sj2);

        char[] c3 = { 'J', 'A', 'V', 'A' };
        String tj1 = new String(c3);
        tj1.intern();
        String tj2 = "JAVA";
        System.out.println(tj1 == tj2);
    }
}

Mag jemand raten, was die Ausgabe ist? (Von Stackoverflow…)

Ich würde mal bei allen 3 auf false tippen soweit ich das mit meinem Smartphone beurteilen kann.
Mal nur geraten: Mit intern() sollte eine neue Instanz im heap angelegt werden, was der Compiler bei den jeweils folgenden String bereits arrangiert hat?

Das wär’ ja langweilig :smiley:

Es wird bei einem false und bei zweien true ausgegeben.

(Das hängt anscheinend auch ein bißchen von der VM ab. In meiner Antwort auf Stackoverflow hatte ich „gezeigt“, dass beim String "true" false ausgegeben wird, was schonmal ein wichtiger Hinweis sein könnte)

Verblüffend. Bei zwei gegen eins könnte man auf die kleingeschriebenen tippen, oder auf die beiden Java-Varianten gegen den anderen. Ich kann aber nur wild raten.

2x false und 1x true, dann kann es nur das 3. sein, denn nur der Wert des 3. kann aus einem vorherigen gebildet werden.

Schönes Beispiel… denn es zeigt, wann == außerdem klappt, obwohl es “nicht” klappen sollte.

Viele nehmen statt equals ja das einfacherere ==; dass es auch funktioniert, wo ein Funktionieren nicht unüberraschend ist, deutet dann direkt auf einen Fehler hin.

Also bei mir
Linux, openjdk version „1.8.0_161“
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode)

kommt dreimal true

Wenn ich grad nichts völlig durcheinander bringe, werden String-Literale erst beim ersten „wirklichen“ benutzen oder eben mit intern in den String-Pool gelegt.
In dem obigen Code ist jeweils die mit new Erzeugte Instanz die, die bei intern im Pool landet, weil sie vor dem Literal benutzt wird. Da der Literal immer der String aus dem Pool ist, ist das dann die gleiche Instanz, wie die mit new Erzeugte.

Das „java“ (und „true“/„false“) dabei Ausnahmen sind, liegt vermutlich daran, dass die in der Oracle-JVM aus irgendeinem Grund schon im String-Pool liegen.

Annähernd richtig (und verständlich)? :sweat_smile:

1 „Gefällt mir“

@AmunRa Ja, bei

char[] ct = { 't', 'r', 'u', 'e' };
String st = new String(ct);
String sti = st.intern();
String sts = "true";
System.out.println(st == sts);// false

könnte/sollte dann aber auch false rauskommen.

Die Antwort von @mrBrown ist „almost certainly correct“ :wink: wie ich auch unter

geschrieben hatte. Der String "java" wird wohl (auf Windows/Oracle etc) schon von der JVM selbst in den Pool gepackt, und man bekommt damit schon eine gepoolte Instanz. In meiner Antwort hatte ich da noch etwas Evidenz untergebracht, mit System#identityHashCode.

Was macht der Compiler mit

switch(string) {
case "m":
// [insert code here]
break;
}

Sprich wie sieht der Code aus wenn man ihn wieder decompilieren würde.

Schauen wir uns das Beispiel an:

public class SWTest {
	public static void main(String[] args) {
		switch(args[0]) {
			case "m":
			System.out.println("the string was m");
			break;
		}
	}
}

Das javap -c SWTest:

Compiled from "SWTest.java"
public class SWTest {
  public SWTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: aload_0
       1: iconst_0
       2: aaload
       3: astore_1
       4: iconst_m1
       5: istore_2
       6: aload_1
       7: invokevirtual #2                  // Method java/lang/String.hashCode:()I
      10: lookupswitch  { // 1

                   109: 28
               default: 39
          }
      28: aload_1
      29: ldc           #3                  // String m
      31: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      34: ifeq          39
      37: iconst_0
      38: istore_2
      39: iload_2
      40: lookupswitch  { // 1

                     0: 60
               default: 68
          }
      60: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      63: ldc           #6                  // String the string was m
      65: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      68: return
}

Das Decompilierte:

import java.io.PrintStream;

public class SWTest
{
  public static void main(String[] paramArrayOfString)
  {
    switch (paramArrayOfString[0])
    {
    case "m": 
      System.out.println("the string was m");
    }
  }
}

Fazit:

Da da sowohl String.hashCode:() wie auch String.equals:( vorkommt, würd’ ich sagen, wird erst auf den Hash geschaut und dann auf den equals…
Außerdem werden daraus zwei Switches!?
Sind Hashes nicht gleich: Sind equals gleich: System.out
Sind Hashes gleich: System.out
Sind Hashes nicht gleich: Sind equals nicht gleich: return

Was ist eigentlich nochmal die Frage gewesen?

String s;
switch ((s = args[0]).hashCode()) { 
            default: break; 
            case -123123: if (s.equals("m")) { 
                System.out.println("the string was m"); } 
                break; 
}

Es war ein Quiz und kein ich schau die Antwort nach :stuck_out_tongue:
Aber ja, er vergleicht den hash Code im Switch statement und im case vergleicht er dann nochmal per equals die Strings direkt.
Irgendwie hatte ich mir das eleganter vorgestellt.