web-dev-qa-db-de.com

Überschreiben gegen versteckendes Java - verwirrt

Ich bin verwirrt darüber, wie Overriding sich von Hiding in Java unterscheidet. Kann jemand mehr Details dazu angeben, wie sich diese unterscheiden? Ich habe das Java Tutorial gelesen , aber der Beispielcode hat mich immer noch verwirrt.

Genauer gesagt verstehe ich das Überschreiben gut. Mein Problem ist, dass ich nicht sehe, dass das Verstecken anders ist, außer der Tatsache, dass sich eine auf Instanzebene befindet, während sich die andere auf Klassenebene befindet.

Schauen Sie sich den Java-Tutorialcode an:

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

Dann haben wir eine Unterklasse Katze:

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

Dann sagen sie:

Die Ausgabe von diesem Programm lautet wie folgt:

Klassenmethode bei Tier.

Die Instanzmethode in Cat.

Für mich ist die Tatsache, dass das Aufrufen einer Klassenmethode testClassMethod () direkt aus der Animal-Klasse die Methode in der Animal-Klasse ausführt, ziemlich offensichtlich, nichts Besonderes. Dann rufen sie testInstanceMethod () von einem Verweis auf myCat auf, also ist es ziemlich offensichtlich, dass die dann ausgeführte Methode die in der Instanz von Cat ist.

Aus dem, was ich sehe, verhält sich das Anrufverstecken wie das Überschreiben. Warum also diese Unterscheidung treffen? Wenn ich diesen Code mit den obigen Klassen ausführen:

Cat.testClassMethod();

Ich bekomme: Die Klassenmethode in Cat. Wenn ich jedoch das testClassMethod () von Cat entferne, erhalte ich: Die Klassenmethode in Animal.

Das zeigt mir, dass das Schreiben einer statischen Methode mit derselben Signatur wie in einer übergeordneten Klasse in einer Unterklasse eine Überschreibung bewirkt.

Hoffentlich mache ich klar, wo ich verwirrt bin und jemand etwas Licht werfen kann. Vielen Dank im Voraus!

64
Lostlinkpr

Übertreiben unterstützt grundsätzlich die späte Bindung. Welche Methode aufgerufen wird, wird daher zur Laufzeit festgelegt. Sie gilt für nicht statische Methoden. Das Ausblenden gilt für alle anderen Member (statische Methoden, Instanzmitglieder, statische Member). Es basiert auf der frühen Bindung. Genauer gesagt, die Methode oder das Element, das aufgerufen oder verwendet werden soll, wird während der Kompilierzeit festgelegt.

In Ihrem Beispiel ist der erste Aufruf Animal.testClassMethod() ein Aufruf einer static-Methode. Daher ist es ziemlich sicher, welche Methode aufgerufen wird.

Beim zweiten Aufruf, myAnimal.testInstanceMethod(), wird eine nicht statische Methode aufgerufen. Es ist, was Sie Laufzeit-Polymorphismus nennen. Erst zur Laufzeit wird entschieden, welche Methode aufgerufen werden soll.

Zur weiteren Erläuterung lesen Sie this .

88
Kazekage Gaara

Statische Methoden werden ausgeblendet, nicht statische Methoden werden überschrieben. Der Unterschied ist bemerkenswert, wenn Aufrufe nicht als "Etwas ()" vs. "This.something ()" qualifiziert werden.

Ich kann mich nicht wirklich auf Worte beschränken, deshalb folgt hier ein Beispiel:

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

AUSGABE:

animal.something
dog.eat
16
WhyNotHugo

Dies ist der Unterschied zwischen Überschreibungen und Verstecken. 

  1. Wenn sowohl die Methode in der übergeordneten Klasse als auch die untergeordnete Klasse eine Instanzmethode sind, werden Überschreibungen genannt.
  2. Wenn sowohl die Methode in der übergeordneten Klasse als auch die untergeordnete Klasse eine statische Methode sind, wird sie als Ausblenden bezeichnet.
  3. Eine Methode kann im Elternteil nicht statisch und im Kind als Instanz sein. und umgekehrt.

enter image description here

11
Rudy

Wenn ich Ihre Frage richtig verstehe, lautet die Antwort "Sie überschreiben bereits".

"Was zeigt mir, dass das Schreiben einer statischen Methode mit dem gleichen Namen wie in einer übergeordneten Klasse in einer Unterklasse eine Überschreibung bewirkt."

Wenn Sie eine Methode in eine Unterklasse mit genau demselben Namen wie eine Methode in einer Superklasse schreiben, überschreibt sie die Methode der Superklasse. Die Annotation @Override muss keine Methode überschreiben. Dadurch wird Ihr Code jedoch lesbarer und der Compiler muss überprüfen, ob Sie tatsächlich eine Methode überschreiben (und beispielsweise die Unterklassenmethode nicht falsch geschrieben haben).

3
thagorn

Das Überschreiben geschieht nur bei Instanzmethoden . Wenn der Typ der Referenzvariablen Animal ist und das Objekt Cat ist, wird die Instanzmethode von Cat aus aufgerufen (dies überschreibt). Für das gleiche acat-Objekt wird die Klassenmethode Animal verwendet. 

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

Ausgabe ist:

The instance method in Cat.
Class method in Animal.
3
yiannis
public class First {

public void Overriding(int i) {  // will be overrided in class Second }

public static void Hiding(int i) {  // will be hidden in class Second
                                    // because it's static }
}

public class Second extends First {

public void Overriding(int i) {  // overrided here  }

public static void Hiding(int i) {  // hidden
                                    // because it's static } 
}

Die Regel für das Auswendiglernen ist einfach: Eine Methode, die die Klasse Erweitert, kann statisch nicht in void ändern und Kann void nicht in statisch ändern. Es wird ein Fehler beim Kompilieren verursacht.

Wenn void Name in void Name geändert wird, ist dies überschrieben. 

Und wenn statischer Name in statischer Name geändert wurde, ist es versteckt. (Wenn der Compiler static method im Objekt der übergeordneten Klasse sieht, prüft er die Methode in der Unterklasse nicht.)

2
p.karnaukhov

In diesem Code-Snippet verwende ich den "privaten" Zugriffsmodifizierer anstelle von "statisch", um den Unterschied zwischen versteckenden und überschreibenden Methoden zu zeigen.

class Animal {
// Use 'static' or 'private' access modifiers to see how method hiding work.
private void testInstancePrivateMethod(String source) {
    System.out.println("\tAnimal: instance Private method calling from "+source);
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Private method.");
    testInstancePrivateMethod( Animal.class.getSimpleName() );
}

// Use default, 'protected' or 'public' access modifiers to see  how method overriding work.
protected void testInstanceProtectedMethod(String source) {
    System.out.println("\tAnimal: instance Protected method calling from "+source);
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Protected method.");
    testInstanceProtectedMethod( Animal.class.getSimpleName() );
  } 
}  


public class Cat extends Animal {
private void testInstancePrivateMethod(String source) {
    System.out.println("Cat: instance Private method calling from " + source );
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("Cat: instance Public method with using of Private method.");
    testInstancePrivateMethod( Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingPrivateMethodInside();
}

protected void testInstanceProtectedMethod(String source) {
    System.out.println("Cat: instance Protected method calling from "+ source );
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("Cat: instance Public method with using of Protected method.");
    testInstanceProtectedMethod(Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingProtectedMethodInside();
}

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("----- Method hiding -------");
    myCat.testInstanceMethodUsingPrivateMethodInside();
    System.out.println("\n----- Method overriding -------");
    myCat.testInstanceMethodUsingProtectedMethodInside();
}
}

Ausgabe:

----- Method hiding -------
Cat: instance Public method with using of Private method.
Cat: instance Private method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Private method.
   Animal: instance Private method calling from Animal

----- Method overriding -------
Cat: instance Public method with using of Protected method.
Cat: instance Protected method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Protected method.
Cat: instance Protected method calling from Animal
1
Rustem Zhunusov

Zur Laufzeit wird die untergeordnete Version einer überschriebenen Methode immer für eine Instanz ausgeführt. Unabhängig davon, ob der Methodenaufruf in einer übergeordneten oder untergeordneten Klassenmethode definiert ist. Auf diese Weise wird die übergeordnete Methode nie verwendet, es sei denn, ein expliziter Aufruf der übergeordneten Methode wird mit der Syntax .__ referenziert. ParentClassName.method () . Alternativ wird zur Laufzeit immer die übergeordnete Version einer verborgenen Methode ausgeführt, wenn der Aufruf der Methode in der übergeordneten Klasse .__ definiert ist.

0
Carrieukie

Wie geschieht das versteckte statische Verfahren in Java? Die Klasse Cat erweitert die Klasse Animal. In Cat-Klasse gibt es also beide statischen Methoden (dh statische Methode der Child-Klasse und statische Methode der Parent-Klasse). Wie geht es in Heap und Stack?

0
user3924979

In der Methode overriding wird die Methodenauflösung von der JVM auf der Grundlage des Laufzeitobjekts durchgeführt. Während beim Ausblenden von Methoden die Methodenauflösung vom Compiler auf der Basis von Referenzen vorgenommen wird. Somit,

Wenn der Code so geschrieben worden wäre,

public static void main(String[] args) {
        Animal myCat = new Cat();        
        myCat.testClassMethod();        
    }

Die Ausgabe wäre wie folgt:
Klassenmethode in Animal.

0
SagarS

Basierend auf meinen aktuellen Java-Studien 

  • method overriding , wenn die Unterklasse dieselbe Methode mit derselben Signatur in der Unterklasse hat.
  • Methode hiding , wenn die Unterklasse denselben Methodennamen, aber einen anderen Parameter hat. In diesem Fall überschreiben Sie die übergeordnete Methode nicht, sondern blenden sie aus.

Beispiel aus dem OCP Java 7-Buch, Seite 70-71:

public class Point {
  private int xPos, yPos;
  public Point(int x, int y) {
        xPos = x;
        yPos = y;
  }

  public boolean equals(Point other){
  .... sexy code here ...... 
  }

  public static void main(String []args) {
   Point p1 = new Point(10, 20);
   Point p2 = new Point(50, 100);
   Point p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //point's class equals method get invoked
  }
}

wenn wir aber folgendes schreiben:

  public static void main(String []args) {
   Object p1 = new Point(10, 20);
   Object p2 = new Point(50, 100);
   Object p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //Object's class equals method get invoked
  }

Im zweiten Hauptbereich verwenden wir die Object-Klasse als statischen Typ. Wenn wir also die Equal-Methode in Point-Objekt aufrufen, wartet sie darauf, dass eine Point-Klasse als Parameter ankommt, aber Object kommt. Also wird die Object-Klasse gleich Methode ausgeführt, weil wir dort ein Gleiches (Object o) haben. In diesem Fall überschreibt die Point-Klasse den Wert nicht, überschreibt jedoch die Object-Klasse-Equals-Methode .

0
Karoly

Auf der verlinkten Java-Tutorial-Seite wird das Konzept des Überschreibens und Ausblendens erläutert

Eine Instanzmethode in einer Unterklasse mit derselben Signatur (Name, plus Nummer und Typ der Parameter) und Rückgabetyp als Instanzmethode in der Superklasse überschreibt die Methode der Superklasse.

Wenn eine Unterklasse eine statische Methode mit der gleichen Signatur wie eine statische Methode in der Oberklasse definiert, blendet die Methode in der Unterklasse die in der Oberklasse aus.

Die Unterscheidung zwischen dem Ausblenden einer statischen Methode und dem Überschreiben einer Instanzmethode hat wichtige Auswirkungen:

  1. Die Version der überschriebenen Instanzmethode, die aufgerufen wird, ist die in der Unterklasse.
  2. Die Version der verborgenen statischen Methode, die aufgerufen wird hängt davon ab, ob sie von der Superklasse oder der Unterklasse aus aufgerufen wird.

Kommen wir zu Ihrem Beispiel zurück: 

Animal myAnimal = myCat;

 /* invokes static method on Animal, expected. */
 Animal.testClassMethod(); 

 /* invokes child class instance method (non-static - it's overriding) */
 myAnimal.testInstanceMethod();

Die obige Aussage zeigt noch kein Verstecken. 

Ändern Sie nun den Code wie folgt, um eine andere Ausgabe zu erhalten:

  Animal myAnimal = myCat;

  /* Even though myAnimal is Cat, Animal class method is invoked instead of Cat method*/
  myAnimal.testClassMethod();

  /* invokes child class instance method (non-static - it's overriding) */
  myAnimal.testInstanceMethod();
0
Ravindra babu

Neben den oben aufgeführten Beispielen wird hier ein kleiner Beispielcode angegeben, um die Unterscheidung zwischen Ausblenden und Überschreiben zu verdeutlichen:

public class Parent {

    // to be hidden (static)
    public static String toBeHidden() {
        return "Parent";
    }

    // to be overridden (non-static)
    public String toBeOverridden() {
        return "Parent";
    }

    public void printParent() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Child extends Parent {

    public static String toBeHidden() {
        return "Child";
    }

    public String toBeOverridden() {
        return "Child";
    }

    public void printChild() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        child.printParent();
        child.printChild();
    }
}

Der Aufruf von child.printParent() gibt aus:
versteckt werden: Elternteil
überschrieben werden: Kind

Der Aufruf von child.printChild() gibt aus:
versteckt werden: Kind
überschrieben werden: Kind

Wie wir an den Ausgaben oben (insbesondere den fett markierten Ausgaben) erkennen können, verhält sich das Methoden-Hiding anders als das Überschreiben.

Java erlaubt sowohl das Ausblenden als auch das Überschreiben nur für Methoden. Die gleiche Regel gilt nicht für Variablen. Das Überschreiben von Variablen ist nicht zulässig, daher können Variablen nur ausgeblendet werden (kein Unterschied zwischen statischen und nicht statischen Variablen). Das folgende Beispiel zeigt, wie die Methode getName() überschrieben und die Variable name ausgeblendet wird:

public class Main {

    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.name); // prints Parent (since hiding)
        System.out.println(p.getName()); // prints Child (since overriding)
    }
}

class Parent {
    String name = "Parent";

    String getName() {
        return name;
    }
}

class Child extends Parent {
    String name = "Child";

    String getName() {
        return name;
    }
}
0
public class Parent {

  public static void show(){
    System.out.println("Parent");
  }
}

public class Child extends Parent{

  public static void show(){
    System.out.println("Child");
  }
}

public class Main {

public static void main(String[] args) {
    Parent parent=new Child();
    parent.show(); // it will call parent show method
  }
}

// We can call static method by reference ( as shown above) or by using class name (Parent.show())
0
Deepak