2015-08-20 11 views
35

Mein Verständnis war, dass statische Variablen und statische Methoden von einer Klasse sind, nicht von den Klassenobjekten. So funktioniert ein Override einer statischen Methode nicht in Java, da zum Überschreiben wir eine Instanz einer Klasse erstellen müssen. Aber ich habe heute etwas versucht, das meinem Java-Wissen widerspricht.Wenn statische Methoden nicht überschrieben werden können, wie funktioniert es hier (für Java)?

Bitte folgen Sie diesen Code:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{  
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Child "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

Der Ausgang der obigen Implementierung ist:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise 
In static method 'doit' of class Parent 
In static method 'doit' of class Child 

Von diesem Ausgang, dass ich kann verstehen, wenn die Child-Klasse erweitert die Parent Klasse, die doit Methoden sind individuell für jede Klasse, wie sie static sind. Also ist kein Überschreiben von ihnen erlaubt.

Nun folgen Sie bitte den Code unten, wo @Override auf die doIt Methode des Kindes hinzugefügt wird:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{  
    @Override // Adding this annotation here 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Child "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

Die Ausgabe des obigen Codes ein Übersetzungsfehler gibt, wie folgt: es

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java 
StaticPractise.java:31: error: method does not override or implement a method from a supertype 
    @Override 
    ^
1 error 

Hier sagt eindeutig, dass die Annotation Override nicht in static Methoden angewendet werden kann, da sie nicht übersteuert werden.

Nun folgen Sie bitte den Code unten, wo Child keine doIt Methode hat:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{ /* no doIt method */ } 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

Die Ausgabe lautet:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise 
In static method 'doit' of class Parent 
In static method 'doit' of class Parent 

Warum der obige Code kompilieren und ausführen? Ich habe einen Kompilierungsfehler für die Methode doit für die Klasse Child erwartet, und ich erwartete "Methode nicht gefunden". Ich verstehe nicht.

Bitte folgen Sie auch den untenstehenden Code. Hier ist die doIt Methode in Parent jetzt final.

class Parent{ 
    public static final void doIt(){ // now final 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

Der Ausgang nach den obigen Code ausgeführt wird, wie folgt:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java 
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent 
    public static void doIt(){ 
        ^
    overridden method is static,final 
1 error 

D:\Rahul Shivsharan\MyPractise\JAVA> 

Was war ich erwartete, dass der obige Code funktionieren sollte, da die doit Methoden in jeder Klasse sind statisch, so dass selbst ein final Schlüsselwort sollte keinen Kompilierungsfehler machen, da die Methode static ist.

Bitte erklären Sie mir, wie Methode überschreiben funktioniert in statischen Klassen in Java.

  1. Können statische Methoden außer Kraft gesetzt werden? Wenn ja, wie kommt es dann, dass das Kommentieren von @Override fehlschlägt?
  2. Wenn statische Methoden nicht überschrieben werden können, wie kommt dann mein dritter Codeblock in Ordnung?Wenn statische Methoden nicht überschrieben werden können, wie kommt dann das Schlüsselwort final?
+2

Gut geschriebene Frage des Tages so weit :) –

Antwort

40

Zunächst einmal gibt es verschiedene Mechanismen, die hier beteiligt: ​​Overriding and Shadowing (also called hiding).

1) Statische Methoden können nicht außer Kraft gesetzt werden, da sie auf die Klasse gebunden sind, sie in definiert sind. Sie können jedoch Schatten/verstecken eine statische Methode, wie Sie mit Ihrem Parent/Child Klasse tun. Das heißt, die Methode wird in der Klasse Child ersetzt, ist aber weiterhin in der Klasse Parent verfügbar.

Es wird deutlicher, dass Sie nicht überschreiben, wenn Sie die statischen Methoden von Instanzen dieser Klassen aufrufen (und nicht den Aufruf Class.staticMethod() verwenden).

Parent parent = new Parent(); 
Child child1 = new Child(); 
Parent child2 = new Child(); 

parent.StaticMethod(); 
child1.StaticMethod(); 
child2.StaticMethod(); 

der Ausgang

Static method from Parent 
Static method from Child 
Static method from Parent 

Die Antwort der Versand der Methoden ist. Sie können die source code here

2) greifen Der Versand findet die Methode auf der Parent Klasse. Es gibt keinen dynamischen Versand, da der Laufzeittyp verwendet wird, um das Methodenhandle zu finden. Es verwendet den Kompilierungszeittyp. Erinnern: Das Aufrufen von statischen Methoden aus Instanzen wird als schlechte Übung angesehen, da Dinge wie oben passieren können und leicht übersehen werden können.

3) Mit final deklarieren Sie, dass die Methode weder überschattet noch versteckt werden kann.

+3

Es sollte weiter beachtet werden, dass der Compiler zu der Verwirrung mit seiner Meldung 'overridden Methode ist statisch, final' hinzugefügt wird. Das sollte stattdessen schattiert/versteckt gelesen haben. – Oliphaunt

6

Sie sind verwirrend overriding mit hiding

+9

Es schleicht mich aus, dass "verwirrend" auch hervorgehoben wird. :/ – EralpB

+0

@EralpB, Ich muss zustimmen ... auf vielfachen Wunsch Link zu Hauptabschnitt in JLS, der in [verwirrend] (https://docs.oracle.com/javase/specs/jls/se8/html/jls- 8.html # jls-8.4.8) wurde gelöscht: D –

3

Obwohl es nicht ratsam ist, 3 Fragen in einem Beitrag zu stellen, bin ich immer noch bereit, sie zu beantworten.

  1. Statische Methoden können nicht überschrieben werden, da es keinen Sinn hat, dies zu tun. In Ihrem Fall, wenn Sie die statische Methode überschreiben möchten, können Sie einfach die Methode aufrufen und danach Ihre eigene Implementierung hinzufügen oder Sie erstellen einfach eine andere Methode.

  2. Jetzt wissen Sie also, dass statische Methoden nicht überschrieben werden können. Aber Sie fragen, warum der dritte Code funktioniert? Eltern {}

rechts Der dritte Code ist der Code mit

public class Child erstreckt? Obwohl statische Methoden nicht überschrieben werden können, können sie geerbt werden. Was Sie tun, erbt Parent, so dass völlig in Ordnung ist!

  1. mich Ihnen Nun lassen Sie sagen, in Ihrem ersten Codebeispiel Sie sind versteckt die Methode in der Parent Klasse überschreiben nicht. Deshalb bekommst du die Ausgabe.A final Schlüsselwort bedeutet, dass die Methode nie geändert werden kann, nicht einmal versteckt. Das ist der Grund.