2015-11-02 17 views
5
class A {int x = 5;} 
class B extends A {int x = 10;} 
class D { 
    public static void main(String[] args){ 
     A b0 = new B(); 
     System.out.print(b0.x); 
    } 
} 

Ich frage mich, warum dieser Code druckt 5 statt 10.statische Instanz Variable Lookup Java

Wenn ich die folgende Stelle schreiben, die Variablen x zu Methoden konvertieren, funktioniert es mehr als ich erwarten würde, und gibt 10 aus, da zur Kompilierzeit lediglich überprüft wurde, ob der statische Typ von b0, A, eine Methode x hat und dann zur Laufzeit den dynamischen Typ B von b0 verwendet, um x auszuführen.

class A {int x() {return 5;}} 
class B extends A {int x() {return 10;}} 
class D { 
    public static void main(String[] args){ 
     A b0 = new B(); 
     System.out.print(b0.x()); 
    } 
} 

Meine Theorie ist, dass Instanzvariablen statisch im Gegensatz zu Methoden nachgeschlagen werden, aber ich bin nicht sicher, warum das so sein würde.

Danke!

Antwort

4

In B das Feld x von A ist beschattet (versteckt) nicht überschrieben. Um zu antworten "warum das wäre" verweist auf die Dokumente here und here. Der Compiler wählt eine der 2 Instanzen von x entsprechend dem Typ des enthaltenden Objekts aus. Und b0 ist vom Typ A

A b0 = new B(); 

Wenn Sie (Getter) Methoden auf der anderen Seite definieren diese können mit der gleichen Signatur überschreiben Methoden in der übergeordneten Klasse. Eine weitere unangenehme Überraschung ist, dass ein Feld in der Elternklasse beschattet wird, auch wenn es sich um einen anderen Typ handelt.

Das Spiegeln von Elementen wird als schlechte Methode betrachtet, da es dazu neigt, Entwickler zu verwirren.

4

Weil Sie auf die Variable x von der Klasse A zugreifen, da b0 als A definiert ist. Es heißt, eine Variable zu verbergen, und nicht, wie Sie vermuten könnten, eine Variable zu überschreiben, was in Java nicht möglich ist. Sie erhalten Ihr erwartetes Ergebnis, wenn Sie mit einem TypCast auf x von b0 zugreifen würden.

A b0 = new B(); 
System.out.print(((B)b0).x); 

Durch eine Rolle festgelegt wurde, müssen Sie die Variable x aus der Klasse zugreifen B jetzt.

für weitere Informationen können Sie lesen durch nicht geerbt JLS 8.3

3

Statische Felder sind, werden sie sich nicht gegenseitig überschreiben, sie einander spiegeln. Wenn Sie in Ihrem Fall direkt auf das gleichnamige statische Feld zugreifen, blendet das Feld der Superklasse das andere Feld aus, und Sie haben zwei int Xes, aber der eine der Superklassen ist nicht versteckt und wird ausgewählt. Noch besser, wenn Sie eine andere Instanz der gleichen Methode aufrufen und auf dasselbe statische Feld zugreifen, dann wird es sehr merkwürdig. Die statischen Felder werden zusammen addiert und Sie können mit X 5 + 5 = 10 enden.

Auf der anderen Seite, wenn Sie nicht statisches Feld von der Oberklasse erben, gibt es kein Problem mit einem anderen Wert in sub Klasse, weil die Unterklasse das nicht statische Superelement überschreiben kann.

Statische Variablen und Vererbung ist schlecht, es bricht den Polymorphismus, wo Sie es am wenigsten erwarten würden. (Tatsächlich, wenn Sie Konzepte Ihrer Sprache verstehen, erwarten Sie es, aber andere Leute können nicht)