Code Rätsel boolean Frage?

4 Antworten

Weil der Compiler die Konkatenation mit dem primitiven int in ein Literal optimiert, das Selbe bei geboxten Integer aber nicht schafft.

Deshalb sind in ersterem Falle die Referenzen gleich, im Letzteren hingegen nicht.

Die Variable str1 wird also komplett wegoptimiert und durch eine Referenz auf den Literal zur Rechten ersetzt, was beim Vergleich also immer zwangsweise true ergeben wird.

str2 hingegen wird tatsächlich zur Laufzeit zusammengebaut und ist damit eine Referenz auf ein völlig anderes Objekt, weshalb hier ein Vergleich immer false liefern wird.

Tipp: Gewöhne dir an, mt einem Decompiler oder Disassembler umzugehen, dann stellen sich solche Fragen gar nicht erst. :)

Woher ich das weiß:Berufserfahrung

Vorweg: Ich könnte falsch liegen, habe mit Java nicht viel am Hut.

Integer ist ein Klasse, kein primitiver Datentyp. Somit hat i2 nicht den Wert 1, sondern ist i2 ein Pointer auf eine Instanz von Integer und speichert somit nur einen Adresswert (Verweis auf ein Objekt auf dem Heap). Um den tatsächlichen Wert (int) vom Integer zum String zu konvertieren, ist wohl Integer.toString() notwendig.

Entsprechend:

String str2 = i2.toString() + s1;
Simon221585  10.02.2020, 17:19

Naja die Typkonvertierung passiert eigentlich automatisch.

0
unsignedInt  10.02.2020, 17:34
@Simon221585

Ah, stimmt. Das Problem liegt natürlich woanders: Es wird versucht, einen Zeiger auf ein String mit "1:ONE" zu vergleichen, was zu Fehlern führt. Korrekt ist, um den Inhalt der Strings zu vergleichen:

  System.out.println(str2.equals("1:ONE"));
  System.out.println(str2.equals("1:ONE"));
0
nobytree2  10.02.2020, 17:33

Das Problem ist weniger der Integer als vielmehr der String. " == " macht tatsächlich einen Referenzabgleich, wohingegen "1:ONE".equals(str1) oder str2.equals("1:ONE") zielführend ist.

Das ist das gefährliche an diesen OOP-Sprachen Java und C#. Bei C++ müsste man sich den Operator selbst schreiben oder kann ihn überladen, dann weiß man, was er macht.

2

Liegt vermutlich daran, weil == Referenzen vergleicht, nicht den Inhalt. Die spannende Frage ist also, warum in einem Fall die Referenz identisch ist, im anderen nicht.

Ich kenen die JVM Spezifikation nicht im Detail, hier wäre meien Vermutung:

String str1 = i1 + s1;

Instanziiert ein Objekt mit dem Inhalt 1:ONE.

Später erhalten die Literale eine Referenz auf dieses Objekt. während

String str2 = i2 + s1;

ein weitere Objekt instanziiert, vermutlich weil eine implizite Konvertierung von Integer nötig ist.

Aber ggf. weiß jemand, der mit Java arbeitet mehr darüber.

Wenn ich die Konstruktion der beiden Strings in der Reihenfolge ändere hat der erst-instanziierte wieder die gleiche Referenz wie das Literal. Interessant. Was die JVM wohl dazu veranlasst?

Was bedeutet ein Gleichheitszeichen bei einem Objekt (String)?

Jeder String ist ein Objekt, auch "1:ONE" ist ein Objekt.

Und nochmals: Wann sind Objekte gleich?

Man nimmt die Objekt-Methode "equals" und nicht " == " bei Strings!

http://www.codeadventurer.de/?p=1689

Woher ich das weiß:eigene Erfahrung – Hobby und teilweise beruflich