Werden statische Methoden in Java geerbt?

141

Ich habe einen Programmierleitfaden zur Java ™ SCJP-Zertifizierung von Khalid Mughal gelesen .

Im Kapitel Vererbung wird dies erklärt

Die Vererbung von Mitgliedern ist eng mit ihrer erklärten Zugänglichkeit verbunden. Wenn auf ein Mitglied der Oberklasse über seinen einfachen Namen in der Unterklasse zugegriffen werden kann (ohne die Verwendung einer zusätzlichen Syntax wie Super), wird dieses Mitglied als geerbt betrachtet

Es wird auch erwähnt, dass statische Methoden nicht vererbt werden. Aber der folgende Code ist vollkommen in Ordnung:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

Wie kann ich direkt display()im Unterricht arbeiten B? Noch mehr B.display()funktioniert auch.

Gilt die Erklärung des Buches nur für Instanzmethoden?

Algorithmusist
quelle
stackoverflow.com/questions/4716040/… hat interessante Informationen.
Mat
Das steht nicht in meinem Exemplar, 1. Auflage. Bitte geben Sie ein aktuelles Angebot an.
Marquis von Lorne

Antworten:

177

Alle Methoden, auf die zugegriffen werden kann, werden von Unterklassen geerbt.

Aus den Sun Java- Tutorials :

Eine Unterklasse erbt alle öffentlichen und geschützten Mitglieder ihres übergeordneten Elements, unabhängig davon, in welchem ​​Paket sich die Unterklasse befindet. Wenn sich die Unterklasse im selben Paket wie ihr übergeordnetes Element befindet, erbt sie auch die paketprivaten Mitglieder des übergeordneten Elements. Sie können die geerbten Mitglieder unverändert verwenden, ersetzen, ausblenden oder durch neue Mitglieder ergänzen

Der einzige Unterschied zu geerbten statischen (Klassen-) Methoden und geerbten nicht statischen (Instanz-) Methoden besteht darin, dass beim Schreiben einer neuen statischen Methode mit derselben Signatur die alte statische Methode nur ausgeblendet und nicht überschrieben wird.

Von der Seite über den Unterschied zwischen Überschreiben und Ausblenden.

Die Unterscheidung zwischen Verstecken und Überschreiben hat wichtige Auswirkungen. Die Version der überschriebenen Methode, die aufgerufen wird, ist die in der Unterklasse. Die Version der versteckten Methode, die aufgerufen wird, hängt davon ab, ob sie von der Oberklasse oder der Unterklasse aufgerufen wird

Yincrash
quelle
So geerbt bezieht sich darauf, ob wir dieses Mitglied in der Unterklasse überschreiben können?
Algorithmist
Nun, das ist Teil der Vererbung, aber nicht alles. Ich würde sagen, die anderen Hauptteile der Vererbung sind Code-Wiederverwendung und Polymorphismus.
Yincrash
Hat die Neudefinition auch einige Regeln wie das Überschreiben?
Surender Thakran
2
@Algorithmist nein nicht genau. Alle Dinge, die Ihre Unterklasse weiter oben in der Hierarchie sieht, sind Dinge, die Ihre Klasse geerbt hat. Vererbte statische Methoden können jedoch nicht überschrieben, sondern nur ausgeblendet werden ("neu deklariert" mit derselben Signatur). Daher können Sie Ihre statischen Methoden auch als endgültig deklarieren, es spielt keine Rolle. Welche statische Methode aufgerufen wird, ist zur Kompilierungszeit bekannt. Bei nicht endgültigen Instanzmethoden muss die Auflösung auf die Laufzeit verschoben werden, da sie möglicherweise überschrieben werden.
Martin Andersson
1
Dein letzter Absatz ist komplett untergraben !!! "Die Version der Überschreibungsmethode, die aufgerufen wird, ist die in der Unterklasse" Dies ist nicht wahr: Angenommen: Die Version der Überschreibungsmethode, die aufgerufen wird, wird nur zur Laufzeit von der JVM bestimmt, die sich auf das Objekt bezieht, das das Objekt erstellt hat Anruf :)
Montag
14

Wenn das das ist, was das Buch wirklich sagt, ist es falsch. [1]

In der Java-Sprachspezifikation # 8.4.8 heißt es:

8.4.8 Vererbung, Überschreiben und Verstecken

Eine Klasse C erbt von ihrer direkten Oberklasse alle konkreten Methoden m (sowohl statisch als auch instanziell) der Oberklasse, für die alle der folgenden Bedingungen zutreffen:

  • m ist ein Mitglied der direkten Oberklasse von C.

  • m ist öffentlich, geschützt oder mit Paketzugriff im selben Paket wie C deklariert.

  • Keine in C deklarierte Methode hat eine Signatur, die eine Unterzeichnung (§8.4.2) der Signatur von m ist.

[1] Das steht nicht in meinem Exemplar, 1. Auflage, 2000.

Marquis von Lorne
quelle
13

Sie können den Unterschied im folgenden Code feststellen, der geringfügig gegenüber Ihrem Code geändert wurde.

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

Dies liegt daran, dass statische Methoden Klassenmethoden sind.

A.display () und B.display () rufen die Methode ihrer jeweiligen Klassen auf.

Gaurav
quelle
1
Das Aufrufen einer statischen Methode für eine Instanz, wie Sie es versuchen, funktioniert in Java nicht.
Lucas C. Feijo
Das erklärt dieses Programm: Das Instanziieren des Objekts von B und das Erwarten, dass die Vererbung funktioniert, ist mit statischen Elementen nicht möglich. Versuchen Sie, denselben Code in Ihre Eclipse / jede Idee aufzunehmen oder mit Javac zu kompilieren, und führen Sie ihn aus
Gaurav,
2
@ LucasC.Feijo eigentlich ich es funktioniert. Zumindest in meiner IDE (Eclipse). Ich bekomme nur eine Warnung. Es ist vielleicht kein guter Stil ... aber das ist eine andere Geschichte.
Dingalapadum
2
@ LucasC.Feijo Aufruf einer statischen Methode für eine Instanz wird nicht empfohlen. Dies funktioniert jedoch genauso wie das Aufrufen einer statischen Methode für einen Klassennamen.
Ziyang Zhang
5

B.display () funktioniert, weil durch die statische Deklaration die Methode / das Mitglied zur Klasse gehört und keine bestimmte Klasseninstanz (auch bekannt als Object). Sie können mehr darüber lesen Sie hier .

Beachten Sie außerdem, dass Sie eine statische Methode nicht überschreiben können. Ihre Unterklasse kann eine statische Methode mit derselben Signatur deklarieren, ihr Verhalten kann jedoch anders sein als erwartet. Dies ist wahrscheinlich der Grund, warum es nicht als vererbt betrachtet wird. Sie können das problematische Szenario und die Erklärung hier überprüfen .

Kai
quelle
2

Statische Methoden werden in Java vererbt, nehmen jedoch nicht am Polymorphismus teil. Wenn wir versuchen, die statischen Methoden zu überschreiben, werden nur die statischen Methoden der Oberklasse ausgeblendet, anstatt sie zu überschreiben.

Praveen Kumar
quelle
Ich sehe keinen Grund, diese Antwort abzulehnen. Es ist klar und deutlich, zumindest der erste Teil. Der zweite Teil sollte nicht zu technisch genommen werden, sonst ist es okay. Zur Verdeutlichung kann sich beim Überschreiben von Methoden der Rückgabetyp (in einen Untertyp) ändern, während dies bei statischen Methoden nicht der Fall ist. Technisch gesehen gilt der Versuch des Überschreibens nicht für statische Methoden. Wir können also nur sagen, dass wir dies nicht können.
Sharhp
2

Dieses Konzept ist nicht so einfach, wie es aussieht. Wir können ohne Vererbung auf statische Mitglieder zugreifen, was eine HasA-Beziehung ist. Wir können auf statische Mitglieder zugreifen, indem wir auch die übergeordnete Klasse erweitern. Das bedeutet nicht, dass es sich um eine ISA-Beziehung (Vererbung) handelt. Tatsächlich gehören statische Mitglieder zur Klasse, und static ist kein Zugriffsmodifikator. Solange die Zugriffsmodifikatoren den Zugriff auf die statischen Elemente zulassen, können wir sie in anderen Klassen verwenden. Wenn es öffentlich ist, ist es innerhalb desselben Pakets und auch außerhalb des Pakets zugänglich. Für Privatpersonen können wir es nirgendwo verwenden. Standardmäßig können wir es nur innerhalb des Pakets verwenden. Aber für geschützte müssen wir die Superklasse erweitern. Das Abrufen der statischen Methode für eine andere Klasse hängt also nicht davon ab, ob sie statisch ist. Dies hängt von den Zugriffsmodifikatoren ab. Also meiner Meinung nach, Statische Mitglieder können zugreifen, wenn die Zugriffsmodifikatoren dies zulassen. Andernfalls können wir sie wie bei der Hasa-Beziehung verwenden. Und hat eine Beziehung ist keine Vererbung. Auch hier können wir die statische Methode nicht überschreiben. Wenn wir eine andere Methode verwenden können, diese aber nicht überschreiben können, handelt es sich um eine HasA-Beziehung. Wenn wir sie nicht überschreiben können, handelt es sich nicht um eine Vererbung. Der Autor war also zu 100% korrekt.

Noman_ibrahim
quelle
Das Erweitern der übergeordneten Klasse ist eine 'is-a'-Beziehung. Wenn der Zugriff privat ist, können Sie ihn innerhalb der Klasse verwenden. 'protected' enthält abgeleitete Klassen und Klassen im aktuellen Paket. Zu viele Fehler hier.
Marquis von Lorne
2

Statische Methoden in Java werden vererbt, können jedoch nicht überschrieben werden. Wenn Sie dieselbe Methode in einer Unterklasse deklarieren, blenden Sie die Oberklassenmethode aus, anstatt sie zu überschreiben. Statische Methoden sind nicht polymorph. Zum Zeitpunkt der Kompilierung wird die statische Methode statisch verknüpft.

Beispiel:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

Sie erhalten Folgendes:

Writing
Writing
Writing
Writing book

quelle
0

Die statische Methode wird in der Unterklasse vererbt, ist jedoch kein Polymorphismus. Wenn Sie die Implementierung einer statischen Methode schreiben, wird die Klassenmethode des übergeordneten Elements nicht ausgeblendet, sondern ausgeblendet. Denken Sie, wenn es nicht vererbt wird, wie können Sie dann ohne zugreifen classname.staticMethodname();?

user4016405
quelle
0

Alle öffentlichen und geschützten Mitglieder können von jeder Klasse geerbt werden, während die Standard- oder Paketmitglieder auch von der Klasse innerhalb desselben Pakets wie das der Oberklasse geerbt werden können. Es hängt nicht davon ab, ob es sich um ein statisches oder ein nicht statisches Element handelt.

Es ist aber auch wahr, dass statische Elementfunktionen nicht an der dynamischen Bindung teilnehmen. Wenn die Signatur dieser statischen Methode sowohl in der übergeordneten als auch in der untergeordneten Klasse gleich ist, gilt das Konzept der Abschattung, nicht der Polymorphismus.

Shubham
quelle
0

Sie können statische Methoden überschreiben. Wenn Sie jedoch versuchen, Polymorphismus zu verwenden, funktionieren diese entsprechend dem Klassenumfang (im Gegensatz zu dem, was wir normalerweise erwarten).

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

Im ersten Fall ist o / p die "in statische Methode von B" # erfolgreiche Überschreibung. Im zweiten Fall ist o / p "in statischer Methode von A" # Statische Methode - berücksichtigt keinen Polymorphismus

Manav Garekar
quelle
-1

Wir können statische Methoden mit derselben Signatur in der Unterklasse deklarieren, dies wird jedoch nicht als überschreibend angesehen, da es keinen Laufzeitpolymorphismus gibt. Da alle statischen Elemente einer Klasse zum Zeitpunkt des Ladens der Klasse geladen werden, entscheidet dies beim Kompilieren Zeit (zur Laufzeit überschreiben) Daher lautet die Antwort "Nein".

NGK
quelle
2
Ich weiß nicht, warum die Leute immer ablehnen und nicht den Grund für die Ablehnung angeben.
surajs1n
Bei dieser Antwort geht es um das Überschreiben. Die Frage betrifft die Vererbung.
Marquis von Lorne
-1

Viele haben ihre Antwort in Worten ausgesprochen. Dies ist eine erweiterte Erklärung in Codes:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

Ergebnisse:

A
B

Test
Test

A
B

Test
Test

A

A

Daher ist dies die Schlussfolgerung:

  1. Wenn wir die Statik statisch über. Aufrufen, sucht sie nach der in dieser Klasse definierten Statik oder der Klasse, die der in der Vererbungskette am nächsten liegt. Dies beweist, dass statische Methoden vererbt werden.
  2. Wenn eine statische Methode von einer Instanz aufgerufen wird, ruft sie die statische Methode auf, die im Typ zur Kompilierungszeit definiert ist.
  3. Eine statische Methode kann von einer nullInstanz aus aufgerufen werden. Ich vermute, dass der Compiler den Variablentyp verwendet, um die Klasse während der Kompilierung zu finden und diesen in den entsprechenden statischen Methodenaufruf zu übersetzen.
Jai
quelle
1
Bloßer Code ist keine Erklärung, sondern eine Demonstration. Eine Antwort auf diese Frage sollte normative Referenzen zitieren und nicht nur das Verhalten einer nicht angegebenen Implementierung zeigen.
Marquis von Lorne
-2

Statische Mitglieder sind universelle Mitglieder. Sie sind von überall zugänglich.

Pavan
quelle
4
kann von überall wörtlich aufgerufen werden , das ist falsch: static! = scope. Vielleicht möchten Sie klarstellen :-)
Kleopatra
Eigentlich ist diese Antwort in Ordnung, wenn man sie wörtlich nimmt. Ich kann mir keinen einzigen Ort im Code vorstellen, an den Code gehen kann, an dem man nicht auf ein statisches Mitglied der Klasse zugreifen kann. Sie können in statischen Initialisierern, statischen Konstruktoren, Instanzkonstruktoren, Methoden, Eigenschaften, in verschiedenen Klassen und in jedem Bereich darauf zugreifen. Solange die Klasse und die statische Methode öffentlich sind, kann von überall auf sie zugegriffen werden, vorausgesetzt, es gibt keine zirkulären Abhängigkeiten von den statischen Initialisierern. Im Wesentlichen werden statische Elemente nicht vererbt, sondern sind nur Methoden auf Klassenebene (dh universelle), auf die von überall aus zugegriffen werden kann.
Triynko
@Triynko Die Antwort ist falsch, wenn private oder paketgeschützte Methoden von außerhalb des Pakets aufgerufen werden.
Marquis von Lorne
@kleopatra - Off-Thema. Java Swing? Verwenden die Leute das heutzutage tatsächlich?
MasterJoe2
@Pavan versucht, private statische Daten von außerhalb der Klasse aufzurufen. Es wird nicht funktionieren.
Rakesh Yadav
-2

Statische Elemente werden nicht an die Unterklasse vererbt, da die Vererbung nur für nicht statische Elemente gilt. Statische Elemente werden vom Klassenladeprogramm in den statischen Pool geladen. Die Vererbung gilt nur für diejenigen Elemente, die in das Objekt geladen werden

Ashwini E.
quelle
Völlig falsch. Siehe JLS # 8.4.8 .
Marquis von Lorne