Gleichheitsaussagen in Java
Einführendes Beispiel
Der Operator »==« ist ein binärer Infixoperator, der es erlaubt, zu schreiben, daß die Werte beider Operanden gleich sind.
Haben beide Operanden denselben Wert, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 1 + 2 );
java.lang.System.out.println( 1 == 2 );
java.lang.System.out.println( 1 == 1 ); }}Protokoll
3
false
true
Morphologie
Dies ist hier nun der erste Operator in diesem Kurs, der als eine lexikalische Einheit mit zwei Zeichen geschrieben wird. (Abgesehen von dem am Anfang des Kurses nur kurz erwähnten Operator »--«.)
Vereinfachte Syntax
- Produktionsregel
Ausdruck
.----------. .--. .----------.
--->| Ausdruck |--->( == )-->| Ausdruck |--->
'----------' '--' '----------'
Die beiden Operanden einer Gleichheitsaussage werden manchmal auch als Komparanden bezeichnet.
Priorität
Die folgende Tabelle gibt die Assoziativität und Priorität der bisher behandelten Operatoren wieder.
- Priorität und Assoziativität der bisher behandelten Operatoren
() Eingeklammerter Ausdruck
() Aufrufoperator
+ - Unaere vorangestellte Operatoren
L * / Multiplikation, Division
L + - Addition, Subtraktion
L == Gleichheitsaussage
R = Zuweisung
Die Priorität des Gleichheitsoperators erlaubt es beispielsweise die Aussage »2 + 3 == 4« oder die Zuweisung »b = 2 == 4« ohne Klammern zu schreiben.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 2 + 3 == 4 );
final boolean b; b = 2 == 4;
java.lang.System.out.println( b ); }}Protokoll
false
false
Ausdrücke ⁺
Die Definition eines Ausdrucks wird um Ausdrücke mit dem neu vorgestellten Operator erweitert.
- Syntaxdiagramm
Ausdruck
.----------.
---.----------->| Literal |------------------------------.---->
| '----------' |
| .----------. |
'----------->| Name |------------------------------'
| '----------' |
| .-. .----------. .-. |
'--->( ( )-->| Ausdruck |-->( ) )----------------------'
| '-' '----------' '-' |
| .----------. |
'----------->| Aufruf |------------------------------'
| '----------' |
| .-. .----------. |
'--->( - )-->| Ausdruck |------------------------------'
| '-' '----------' |
| .-. .----------. |
'--->( + )-->| Ausdruck |------------------------------'
| '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |--->( / )---->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |--->( + )---->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |--->( - )---->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |--->( * )---->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .--. .----------. |
'----------->| Ausdruck |--->( == )--->| Ausdruck |----'
| '----------' '--' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |--->( = )---->| Ausdruck |----'
'----------' '-' '----------'
Typen
Kurz gesagt sind Vergleiche mit »==« vor allem dann sinnvoll, wenn beide Operanden den Typ »int« haben, da Vergleiche mit Ausdrücken der meisten anderen Typen zu gewissen Problemen führen könnten.
Typanforderungen (vereinfacht) ⃗
Die Typen der beiden Operanden müssen entweder gleich sein oder es muß sich um eine Kombination von »int« und »double« handeln. Im zweiten Falle wird der int -Wert vor dem Vergleich nach »double« gewandelt.
- Mögliche Gleichheitsaussagen (symbolische Schreibweise)
int == int
java.lang.String == java.lang.String (erlaubt, aber kein Textvergleich!)
boolean == boolean
double == doubleint == double (als double == double)
double == int (als double == double)
Wie weiter unten erklärt werden wird, sind Vergleiche von java.lang.String- und double-Werten selten sinnvoll, und Vergleiche von boolean-Werten sind selten. Damit kann man für den Anfang davon ausgehen, daß der Operator »==« vorwiegend für den Vergleich zweier int-Werte eingesetzt wird.
Typangleichung ⃗
Der Wert von »7« und der Wert von »7.« sind unterschiedlich, da diese Ausdrücke zwei verschiedene Datentypen haben. Bei der Aussage »7==7.« wird der Wert »7« aber zunächst nach »double« gewandelt. Es wird dann praktisch »7.==7.« ausgewertet. Daher ergibt »7==7.« true, obwohl die Werte eigentlich unterschiedlich sind, da sie sich in den Datentypen unterscheiden. Dies führt aber in der Praxis nicht zu Problemen, sondern ist meist eher nützlich. Falls einem dies mißfällt, kann man ja darauf verzichten, Gleichheitsaussagen mit Operanden unterschiedlicher Typen zu formulieren oder sich eine eigene Methode für Vergleiche definieren.
Typ des Ausdrucks ⃗
Der Typ eines mit diesem Operator gebildeten Ausdrucks zur Gleichheitsaussage ist immer »boolean«.
Semantik ⃗
Semantik (allgemein) ⃗
Bei der Auswertung dieses Operators werden zunächst immer beide Operanden ausgewertet.
Semantik (Wert) bei gleichen Typen ⃗
Haben beide Ausdrücke denselben Typ, dann gilt: haben beide Ausdrücke denselben Wert, so ist der Wert der Gleichheitsaussage »true«, sonst »false«. (Jedoch ist diese Erklärung für den Datentyp »java.lang.String« etwas trügerisch. Vergleiche von Zeichenfolgen werden erst im Aufbaukurs richtig erklärt – bis dahin sollte man noch auf sie verzichten!)
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 1 == 2 );
java.lang.System.out.println( 0.0 == 0.00 );
java.lang.System.out.println( "2.0" == "1.9999999999999999" );
java.lang.System.out.println( true == false ); }}Protokoll
false
true
false
false
Semantik (Wert) bei int==double-Vergleichen ⃗
Sind die Werte beider Ausdrücke nach der Wandlung in den Typ »double« gleich, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Semantik (Wert) bei double==double-Vergleichen ⃗
Bei double==double-Vergleichen kann das Ergebnis des Vergleichs anders sein als man es erwartet, wenn man die Rechnungen im Kopf durchführt.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 0.1 + 0.2 == 0.3 );
java.lang.System.out.println( 1.1 * 1.1 == 1.21 );
java.lang.System.out.println( 1E30 == 1E30 + 1 );
java.lang.System.out.println( 9_007_199_254_740_993. == 9_007_199_254_740_992. ); }}- Protokoll
false
false
true
true
Da das Ergebnis von double==double-Vergleichen zu sehr von kleinsten Abweichungen in den hintersten Stellen abhängen kann, sind Aussagen zur Gleichheit von double-Werten in der Regel nicht sinnvoll.
Jedoch können Vergleiche von double-Werten doch sinnvoll sein, wenn diese ganzzahlig und nicht zu groß sind.
Semantik (Wert) bei Vergleichen von Laufzeitwerten ⃗
Obwohl in dem folgenden Programm beide Operanden »java.lang.Math.random()« (als Quelltext) genau gleich sind, ergibt der Vergleich doch »false«.
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
Dies liegt daran, daß jede Auswertung des Ausdrucks »java.lang.Math.random()« einen neuen Laufzeitwert ergibt, der sich von dem Wert einer anderen Auswertung desselben Ausdrucks unterscheiden kann.
Semantik (Wert) bei String==String-Vergleichen ⃗
Die Bedeutung von java.lang.String -Vergleichen wird erst später ausführlicher behandelt werden. Bis dahin sollten sie noch vermieden werden. Das folgende Programmbeispiel zeigt, daß ihr Ergebnis nicht immer so ist, wie man es ohne Vorkenntnisse erwarten würde.
Die Ausgabe der Zeichenfolgen »l« und »r« zeigt, daß beide aus denselben drei Zeichen »0.0« bestehen, aber der Vergleich mit »==« ergibt falsch. Deswegen sollten Vergleiche von Zeichenfolgen mit »==« bis auf weiteres noch nicht verwendet werden.
Main.java
public final class Main
{public static void main( final java.lang.String[] args )
{ final java.lang.String l = 0. * java.lang.Math.random()+ "";
final java.lang.String r = "0.0";
java.lang.System.out.println( l );
java.lang.System.out.println( r );
java.lang.System.out.println( l == r ); }}Protokoll
0.0
0.0
false
Semantik (Wert) bei boolean==boolean-Vergleichen ⃗
Wahrheitswerte können ohne weiteres verglichen werden. Man erhält die erwarteten Ergebnisse.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( true == false );
java.lang.System.out.println( false == false ); }}Protokoll
false
true
Der Operator »==« ist linksassoziativ. Entsprechend bedeutet »false == false == false« beispielsweise dasselbe wie »( false == false )== false«, also »true == false«, was »false« ergibt.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( false == false == false );
java.lang.System.out.println( true == true == true ); }}Protokoll
false
true
Zur Auswertung von »false == false == false«:
- erste (linke) Gleichheitsaussage
_____________
false == false == false →
true == false- zweite Gleichheitsaussage
true == false →
false
Der Gleichheitsoperator »==« und der Zuweisungsoperator »=« ⃗
Man beachte die Unterscheidung zwischen dem Zuweisungsoperator »=« und dem Gleichheitsoperator »==«. Beide sind jeweils eine lexikalische Einheit, die erste schreibt sich jedoch mit einem Gleichzeichen »=«, die zweite mit zwei Gleichzeichen »==«.
Der Zuweisungsoperator »=« ist ein Wertwirkoperator, während der Gleichheitsoperator »==« ein reiner Wertoperator ist.
Selbst, wenn man dies weiß, ist es ein häufiger Flüchtigkeitsfehler, versehentlich statt »==« den Operator »=« zu verwenden. Manchmal wird »false == x« statt »x == false« geschrieben, da ersteres mit Sicherheit eine Fehlermeldung ergibt, wenn versehentlich ein Gleichheitszeichen weggelassen wird.
Wenn keine Verwechslungen mit einer Zuweisung zu befürchten sind, kann man den Operator »==« als „(ist) gleich“ aussprechen. Sind Verwechslungen zu befürchten, so muß er genauer als „Gleichheitsaussage“ oder ähnlich bezeichnet werden.
Die mathematische Schreibweise des Operators »==« ist ‹=› (ein einfaches Gleich-Zeichen). (Für die Java -Zuweisung »=« gibt es in der Mathematik keine genaue Entsprechung.)
Beispiele ⃗
● Gleiche Werte bei verschiedenen Ausdrücken ⃗
Wir können nun deutlich erkennen, daß verschiedene Ausdrücke den gleichen Wert haben können, was noch einmal den Unterschied zwischen Ausdrücken und Werten verdeutlicht.
Main.java
public final class Main
{public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 12.0 == 12.00 );
java.lang.System.out.println( 12 == +12 );
java.lang.System.out.println( 12 == 6+6 ); }}Protokoll
true
true
true
● Attribute ⃗
In dem folgenden Programm wird ein Attribut »ist_sieben« definiert, das es erlaubt, die Aussage zu schreiben, daß eine Zahl gleich Sieben sei.
Main.java
public final class Main
{public static boolean ist_sieben( final int zahl )
{ return 7 == zahl; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( ist_sieben( 6 ));
java.lang.System.out.println( ist_sieben( 7 ));
java.lang.System.out.println( ist_sieben( 8 )); }}Protokoll
false
true
false
Solch eine Methode nennen wir auch einen Detektor (eine Detektormethode für die Zahl »7«, sie erkennt [„detektiert“] die Zahl »7«, indem sie nur für diese Zahl »true« ergibt).
Übungsfragen
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 2 == 2 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 2 == 3 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( 3 == 2 + 1 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static void method( final int zahl )
{ java.lang.System.out.println( zahl == 0 ); }public static void main( final java.lang.String[] args )
{ method( 3 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static void method( final int zahl )
{ java.lang.System.out.println( zahl - 3 == 0 ); }public static void main( final java.lang.String[] args )
{ method( 2 + 1 );
method( 2 + 0 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static boolean id( final boolean wert )
{ return wert; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( id( false ));
java.lang.System.out.println( id( true )); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static boolean f( final boolean wert )
{ return true == wert; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( f( false ));
java.lang.System.out.println( f( true )); }}
? Übungsfrage ⃖
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static boolean f( final boolean wert )
{ return false == wert; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( f( false ));
java.lang.System.out.println( f( true )); }}
? Übungsfrage ⃖
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static boolean f( boolean wert )
{ return wert = false; }public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( f( false ));
java.lang.System.out.println( f( true )); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{public static void method( final int zahl )
{ java.lang.System.out.println( 3 == zahl == false ); }public static void main( final java.lang.String[] args )
{ method( 2 + 0 );
method( 2 + 1 ); }}
? Übungsfrage *
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ boolean wert = false;
java.lang.System.out.println( wert = wert == false ); }}
? Übungsfrage *
Ergibt die im folgenden deklarierte Methode »m« immer true ?
- Methodendeklaration
public static boolean m( final int a )
{ return java.lang.Math.abs( -a )== a; }
? Übungsfrage *
Welche Ausgabe erzeugt das folgende Programm?
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ boolean a = false;
boolean b = true;
boolean c = false;
boolean d = true;
java.lang.System.out.println( a = b = c == d );
java.lang.System.out.println( a = b == c == d ); ); }}
Übungsaufgaben
/ Nulldetektor ⃖
Schreiben Sie eine Methode »isZero(int)«, die genau dann »true« ergibt, wenn sie mit »0« aufgerufen wird.
Dazu soll die Linie in dem folgenden Programmrahmen durch einen geeigneten Text ersetzt werden.
Wenn die Methode richtig geschrieben wurde, gibt das Programm immer nur »true« aus.
Main.java
public final class Main
{public static boolean isZero( final int i ){ _______ }
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( isZero( 0 )== true );
java.lang.System.out.println( isZero( 1 )== false );
java.lang.System.out.println( isZero( -1 )== false );
java.lang.System.out.println( isZero( 2 )== false );
java.lang.System.out.println( isZero( -2 )== false ); }}transcript
true
true
true
true
true
/ Gleichheitsmethode ⃖
Schreiben Sie eine Methode »areEqual(int,int)«, die genau dann »true« ergibt, wenn sie mit zwei gleichen Zahlen aufgerufen wird.
Wenn die Methode richtig geschrieben wurde, gibt das Programm immer nur »true« aus.
Main.java
public final class Main
{public static boolean areEqual( final int i, final int j ){ … }
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( areEqual( 0, 0 )== true );
java.lang.System.out.println( areEqual( 0, 1 )== false );
java.lang.System.out.println( areEqual( 1, 0 )== false );
java.lang.System.out.println( areEqual( 1, 1 )== true ); }}transcript
true
true
true
true
/ Ungleichheitsmethode
Schreiben Sie eine Methode »areNotEqual(int,int)«, die genau dann »true« ergibt, wenn sie mit zwei verschiedene Zahlen aufgerufen wird.
Wenn die Methode richtig geschrieben wurde, gibt das Programm immer nur »true« aus.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( areNotEqual( 0, 0 )== false );
java.lang.System.out.println( areNotEqual( 0, 1 )== true );
java.lang.System.out.println( areNotEqual( 1, 0 )== true );
java.lang.System.out.println( areNotEqual( 1, 1 )== false ); }}transcript
true
true
true
true
/ Exklusiv-Oder
Schreiben Sie eine Methode »xor(boolean,boolean)«, die genau dann »true« ergibt, wenn genau einer der beiden Wahrheitswerte »true« ist.
Wenn die Methode richtig geschrieben wurde, gibt das Programm immer nur »true« aus.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( xor( false, false )== false );
java.lang.System.out.println( xor( false, true )== true );
java.lang.System.out.println( xor( true, false )== true );
java.lang.System.out.println( xor( true, true )== false ); }}transcript
true
true
true
true
/ Umwandlung 1 *
Schreiben Sie eine Methode »bool(int)«, die von »int« nach »boolean« „wandelt“. Sie soll für den Argumentwert »0« das Ergebnis false haben und sonst immer true ergeben.
Wenn die Methode in den folgenden Testrahmen eingesetzt wird, soll immer nur »true« ausgegeben werden.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( bool( 0 )== false );
java.lang.System.out.println( bool( 1 )== true );
java.lang.System.out.println( bool( -1 )== true );
java.lang.System.out.println( bool( 2 )== true );
java.lang.System.out.println( bool( -2 )== true ); }}transcript
true
true
true
true
true
/ Teilbarkeitsprädikat *
Schreiben Sie eine Methode »vierTeilt«, die dann und nur dann »true« ergibt, wenn ihr int-Argument durch »4« teilbar ist.
(Es reicht, wenn diese Methode für nicht-negative Werte das richtige Ergebnis liefert.)
Wenn die Methode in den folgenden Testrahmen eingesetzt wird, soll immer nur »true« ausgegeben werden.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( vierTeilt( 0 )== true );
java.lang.System.out.println( vierTeilt( 1 )== false );
java.lang.System.out.println( vierTeilt( 2 )== false );
java.lang.System.out.println( vierTeilt( 3 )== false );
java.lang.System.out.println( vierTeilt( 4 )== true );
java.lang.System.out.println( vierTeilt( 5 )== false );
java.lang.System.out.println( vierTeilt( 6 )== false );
java.lang.System.out.println( vierTeilt( 7 )== false );
java.lang.System.out.println( vierTeilt( 8 )== true );
java.lang.System.out.println( vierTeilt( 9 )== false ); }}transcript
true
true
true
true
true
true
true
true
true
true
/ Ganz *
Schreiben Sie ein Prädikat »ganz« mit einem double-Parameter, so daß eine Inkarnation jenes Prädikats den Wert »true« genau dann hat, wenn der Wert des Arguments jener Inkarnation keine Nachkommastellen (außer »0«) hat.
Main.java
public final class Main
{…
public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( ganz( 0.5 )== false );
java.lang.System.out.println( ganz( 1.5)== false );
java.lang.System.out.println( ganz( -1 ) );
java.lang.System.out.println( ganz( 0 ));
java.lang.System.out.println( ganz( 1 ));
java.lang.System.out.println( ganz( 2 )); }}- Protokoll
true
true
true
true
true
true
/ Prädikate *
Schreiben Sie folgende Prädikate (Methodendeklarationen):
- »isLessThan(int,int)« ergibt »true« genau dann, wenn der erste Argumentwert kleiner als der zweite ist. (Das dürfte schwierig werden, da »<«, »<=«, »>« oder »>=« bisher ja noch nicht behandelt wurden und daher bei der Lösung nicht verwendet werden dürfen), es reicht, wenn das Ergebnis für Argumentwerte zwischen 1 [einschließlich] und 10000 [einschließlich] stimmt.)
- »isLessThanOrEqual(int,int)« ergibt »true« genau dann, wenn der erste Argumentwert kleiner als der zweite oder gleich dem zweiten ist. (Es gilt hier ebenfalls das bei der vorigen Aufgabe in den Klammern Gesagte.)
Es dürfen nur die im Kurs bisher schon vorgestellten Sprachelemente verwendet werden!
Das Zuweisungsprinzip *
Das Zuweisungsprinzip stellt eine Beziehung zwischen dem Operator »=« und dem Operator »==« her: direkt nach einer Zuweisung an eine Variable ergibt ein Vergleich der Variablen mit dem zugewiesenen Wert true.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ int v;
v = 2;
java.lang.System.out.println( v == 2 ); }}java.lang.System.out
true