Die Objektregel für Namen in Java
Die Typtoleranz
Wie schon im Grundkurs behandelt, muß der Typ eines Namens nicht unbedingt der Typ des Initialisierungsausdrucks sein, es reicht, wenn der Typ des Namens ein Obertyp des Typs des Initialisierungsausdrucks ist.
ℛ Substitutionsprinzip für Initialisierungsausdrücke Der Typ des Initialisierungsausdrucks muß ein Untertyp des Typs der zu initialisierenden Variablen sein.
ℛ Objektregel Der Typ eines Objektes muß ein Untertyp des Typs eines Ausdrucks (also auch eines Namens) für das Objekt sein.
- Ausdrücke und Typen
final java.lang.Object o = "abc";
Ausdruck Typ des Ausdrucks Typ des Objekts
"abc" java.lang.String java.lang.String
o java.lang.Object java.lang.StringMain.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final java.io.PrintStream out = java.lang.System.out;final java.lang.CharSequence s = "abc"; out.println( s );
final java.lang.Object o = s; out.println( o ); }}- Protokoll
abc
abc
Wenn der Typ des Names ein Obertyp des Typs des Initialisierungsausdrucks auf der rechten Seite des Gleichheitszeichens »=« ist und der Wert des Initialisierungsausdrucks ein Objekt ist, dann ist der Typ des Namens auch ein Obertyp des Typs des Objektes, weil der Typ des Initialisierungsausdrucks ja ein Obertyp des Typs des Objektes sein muß. In »o = s« (in dem obigen Programmbeispiel) ist der Typ des Namens beispielsweise »java.lang.Object«, der Typ des Initialisierungsausdrucks ist »java.lang.CharSequence« und der Typ des Objekts ist »java.lang.String«, hier ist »java.lang.Object« ein Obertyp von »java.lang.CharSequence«, welches seinerseits wiederum ein Obertyp von »java.lang.String« ist.
Daher führt die Einhaltung des Substitutionsprinzip für Initialisierungsausdrücke dazu, daß auch die Objektregel für den deklarierten Namen erfüllt ist.
- Typbeziehungen
java.lang.Object > java.lang.CharSequence > java.lang.String
Allerdings muß der Typ des Namens auch wirklich ein Obertyp des Typs des Ausdrucks sein. Es reicht nicht, wenn er lediglich ein Obertyp des Typs des Objekts ist. Der Compiler kennt nämlich den Typ des Objekts nicht, so daß er nicht erkennen kann, daß ein Typ in bestimmten Fällen zulässig sein sollte.
Beispiel ⃗
In dem folgenden Beispiel sollte der Typ »java.io.FilterInputStream« des Namens »in« für das Objekt der Klasse »java.io.BufferedInputStream« als Obertyp eigentlich zulässig sein. Der Initialisierungsausdruck »java.lang.System.in« hat jedoch den Typ »java.io.InputStream«, und dieser ist kein Untertyp des Typs »java.io.FilterInputStream« des Namens »in«.
Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final java.io.FilterInputStream in = java.lang.System.in; }}transcript
Main.java:3: error: incompatible types: InputStream cannot be converted to FilterInputStream
{ final java.io.FilterInputStream in = java.lang.System.in; }}
^
1 error- Ausschnitt aus der Typhierarchie
java.io.InputStream Klasse des Ausdrucks "System.in"
^
/_\
|
java.io.FilterInputStream Klasse des Namens "in"
^
/_\
|
java.io.BufferedInputStream Klasse des Objekts "System.in"
In diesem Beispiel ist die Objektregel, die besagt, daß der Typ eines Objektes ein Untertyp des Typs seines Ausdrucks sein muß, zwar eingehalten worden, aber die Initialisierungsregel, die besagt, daß der Typ eines Initialisierungsausdrucks ein Untertyp des Typs der zu initialisierenden Variablen sein muß, wurde hier verletzt. (Diese Regeln werden im folgenden Abschnitt noch einmal genannt.)