Referenzen und Vergleiche in Java (Referenzen und Vergleiche in Java), Lektion, Seite 723447
https://www.purl.org/stefan_ram/pub/nachrichten_an_klassen_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram

Einführung

Referenzen werden in Java  nicht immer  automatisch dereferenziert.

Bei der Verwendung des Operators »==« stehen die Referenzen für sich selbst. Daher vergleich dieser Operator Referenzen und nicht Objekte.

Um zu ermitteln, ob ein Objekt einen Zustand hat, der dem Zustand eines anderen Objektes als gleich angesehen wird, verwendet man den Methodennamen »equals«, dessen Bedeutung durch die Sprache »java.lang.Object« definiert wird.

Identität erzeugter Objekte

Das nächste Beispiel vergleicht zwei erzeugten Objekte miteinander.

Creation2.java
public final class Main 
{ public static void main( final java.lang.String[] args ) 
{ java.lang.System.out.println( new java.lang.Object() == new java.lang.Object() ); }}

System.out
false

Das Ergebnis des Vergleichs erscheint absurd, wenn die beiden Operanden des Vergleichsoperators betrachtet werden: Auf der linken Seite steht genau das gleiche wie auf der rechten Seite. Wie kann es sein, daß die beiden Seiten dann nicht gleich sind?

Das wird allerdings verständlicher, wenn man bedenkt, daß Ausdrücke eben keine Terme sind: Der Wert eines mathematischen Terms  ist durch den Term bestimmt. Der Wert eines Ausdrucks  kann hingegen auch durch andere Umstände bestimmt sein. Der Ausdruck links  vom Gleichheitsprüfungsoperator "==" ist eben das bei der Auswertung der linken Seite  "new java.lang.Object()" erzeugte Objekt, der Ausdruck auf der rechten Seite ist ein anderes  bei der Auswertung der rechten Seite  "new java.lang.Object()" erzeugte Objekt. Es handelt sich also um zwei unterschiedliche  Objekte, die als Wirkung der Auswertung eines Ausdrucks entstanden sind. Der Operator "==" zwischen zwei Referenzausdrücken vergleicht die Objekte seiner beiden Operanden, und die sind hier ungleich.

Ein Erzeugungsausdruck mit dem Schlüsselwort "new" ist wie eine Maschine, die ein neues Objekt der Klasse herstellt. Dabei legt die Klasse die Methoden des Objekts fest.

Das Phänomen, daß zwei Auswertungen desselben  Ausdrucks unterschiedliche  Werte ergeben können, findet man auch schon bei den elementaren Werten.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( java.lang.Math.random() == java.lang.Math.random() ); }}
Protokoll
false

Erzeugung und Benennung eines Objekts

Bei der Auswerung von »s.equals( t )« wird die Nachricht »equals( t )« an das Objekt »s« geschickt. Wenn die Nachricht »equals( t )« an »s« geschickt wird, vergleicht sich »s« mit »t«. Das Ergebnis ist genau dann »true« wenn „Gleichheit“ festgestellt wurde.

Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ final java.lang.String s = new java.lang.String();
final java.lang.String t = new java.lang.String();
java.lang.System.out.println( s );
java.lang.System.out.println( t );
java.lang.System.out.println( s == t );
java.lang.System.out.println( s.equals( t )); }}
transcript


false
true

Erzeugungs-Argumente

In einem Erzeugungsausdruck können auch Argumente verwendet werden, für die die Klasse des zu erzeugenden Objektes allerdings entsprechende Signaturen implementieren muß. Das bedeutet, daß die Zahl, der Typ und die Bedeutung der angegebenen Argumente von der voranstehenden Klasse abhängt.

Beispielsweise kann zu einer Kette eine neue Kette erzeugt werden. Obwohl die neue Kette den gleichen Text enthält, handelt es sich dann doch um eine andere Kette.

Main.java
public class Main 
{ public static void main( final java.lang.String[] args ) 
{ final java.lang.String s = new java.lang.String( "Hallo!" ); 
final java.lang.String t = new java.lang.String( "Hallo!" ); 
java.lang.System.out.println( s ); 
java.lang.System.out.println( t ); 
java.lang.System.out.println( s == t ); 
java.lang.System.out.println( s.equals( t )); }}

System.out
Hallo! 
Hallo! 
false 
true

Man beachte daß in der Deklaration "final String s = new String( "Hallo!" );" der Typ "String" zwiefach auftritt: Zuerst als Typ der Konstanten "s" und dann also Typ eines neu anzulegenden Objekts.

Ein beliebter Flüchtigkeitsfehler kann es sein, das Schlüsselwort "new" zu vergessen, da die scheinbare Deklaration "final String s = String( "Hallo!" );" auch plausibel aussieht.

Bei Verwendung eines String-Literals ist die ausdrücklich Erzeugung mit einem Erzeugungsausdruck natürlich meist unnötig kompliziert, da anstelle des Ausdrucks "new String( "Hallo!" )" meistens der Ausdruck ""Hallo!"" verwendet werden kann.

Objekte und ihre „Identität“

Das folgende Programm zeigt, daß Objekte mit gleichem  Zustand (»equals«) trotzdem als unterschiedlich ==«) angesehen werden können, wie sie unterschiedliche Speicherorte (Referenzen) haben.

Main.java
public class Main
{ public static void main( final java.lang.String[] args )
{ final java.awt.geom.Point2D.Double o0
= new java.awt.geom.Point2D.Double();
final java.awt.geom.Point2D.Double o1
= new java.awt.geom.Point2D.Double();
o0.x = 1; o0.y = 2;
o1.x = 1; o1.y = 2;
java.lang.System.out.println( o0.equals( o1 ));
java.lang.System.out.println( o0 == o1 ); }}
transcript
true
false

Manche sagen dazu auch „Objekte haben eine Identität.“, die beiden Objekte »o0« und »o1« haben zwei verschiedene Identitäten, obwohl ihre Zustände (die Werte beider Felder) einander gleich sind.

Gelten zwei Ausdrücke für Referenzen als gleichwertig, wenn (sie beide nicht die Nullreferenz sind und) alle Felder der beiden Objekte die gleichen Werte haben, so nennt man dies auch einen strukturellen Gleichheitsbegriff. Im Gegensatz dazu steht der Referenzgleichheitsbegriff, bei dem zwei Referenzausdrücke als gleichwertig gelten, wenn sie beide dieselbe Referenz als Wert haben.

Wir finden den Begriff „Identität“ etwas vage und sagen statt dessen lieber: Die beiden Objekte »o0« und »o1« sind gleich, wenn man nur die Werte in ihren Feldern betrachtet, aber ungleich, wenn man auch noch ihre Speicherorte (=Referenzen) in die Betrachtung mit einbezieht. Im Falle der Klasse »java.awt.geom.Point2D.Double« vergleicht »equals« nur die beiden Felder und »==« vergleicht nur die Referenzen. (Wenn zwei Variablen bei einem Vergleich mit »==« ergeben, dann referenzieren sie beide allerdings dasselbe Objekt, und daher muß dann auch der Vergleich ihrer Felder Gleichheit ergeben.)

Dokumentation von Erzeugungs-Argumente

Die Dokumentation der möglichen Argumente eines Erzeugungsausdrucks findet sich unter “Constructor Summary ” in der verwendeten Klasse.

Erzeugungsparameter

Der Wert des Erzeugungsausdrucks »new java.lang.Integer( 0 )« ist eine Referenz auf Objekt vom Typ »java.lang.Integer« mit dem Wert »0«. Der Ausdruck »0« ist ein Argument  dieses Erzeugungsausdrucks. Woher weiß man aber, welche Argumente hier zulässig sind? Das kann der Dokumentation der Klasse »java.lang.Integer« entnommen werden.

java.lang.Integer-Erzeugungsparameter (Synopse)

java.lang

Class java.lang.Integer

Constructor Summary

Integer( int value )

Constructs a newly allocated Integer object that
represents the primitive int argument.

Integer( String s )

Constructs a newly allocated Integer object that
represents the value represented by the string.

Die Dokumentation der Klasse gibt hier an, daß eine Erzeugungsoperation mit einem Parameter vom Typ »int« und eine Erzeugungsoperation mit einem Parameter vom Typ »java.lang.String« unterstützt wird.

Ein Erzeugungsparameter kann als sowohl ein Wert eines elementaren Typs als auch ein Objekt einer Klasse sein.

Der folgende Quellcode zeigt die Verwendung beider Typen.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final java.lang.Integer p = new java.lang.Integer( 4 );
final java.lang.Integer q = new java.lang.Integer( "4" );
final java.lang.Integer r = new java.lang.Integer( new java.lang.String( "4" ));
java.lang.System.out.println( p.equals( q ));
java.lang.System.out.println( q.equals( r )); }}
transcript
true
true

In dem folgenden Programm werden zwei verschiedene  java.lang.Integer-Objekte mit dem gleichen Wert erzeugt.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final java.lang.Integer p = new java.lang.Integer( 2 );
final java.lang.Integer q = new java.lang.Integer( 2 );
java.lang.System.out.println( p.equals( q ));
java.lang.System.out.println( p == q ); }}
transcript
true
false

Wir können nun zeigen, daß »"abc"« immer für das gleiche Objekt steht.

Main.java
final public class Main
{ final public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( "abc" == "abc" );
final java.lang.String abc = "abc";
java.lang.System.out.println( abc == "abc" ); }}
Protokoll
true
true

Eine Verkettung von Kettenliteralen ergibt das gleiche Stringobjekte für den gleichen Text. Die Klasse "Main" illustriert, daß die Verkettung nicht immer ein neues Objekt erzeugt.

Main.java
final public class Main
{ final public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( ( "Ha" + "us" ).equals( "Haus" ) ); /* true */
java.lang.System.out.println( "Ha" + "us" == "Haus" ); /* true */
java.lang.System.out.println( "Haus" == new java.lang.String( "Haus" ) ); /* false */
java.lang.System.out.println( "Haus".equals( new java.lang.String( "Haus" ))); /* true */ }}
transcript
true
true
false
true

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723447 stefan_ram:723447 Referenzen und Vergleiche in Java Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723447, slrprddef723447, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/nachrichten_an_klassen_java