Что скрывает метод в Java? Даже объяснение JavaDoc сбивает с толку

Javadoc говорит:

версия скрытого метода, который вызывается, является таковой в суперклассе, а версия переопределенного метода, который вызывается, является таковой в подклассе.

не звонит мне. Любой четкий пример, показывающий смысл этого, будет высоко оценен.

Ответ 1

public class Animal {
    public static void foo() {
        System.out.println("Animal");
    }
}

public class Cat extends Animal {
    public static void foo() {  // hides Animal.foo()
        System.out.println("Cat");
    }
}

Здесь Cat.foo() как говорят, скрывает Animal.foo(). Сокрытие не работает как переопределение, потому что статические методы не полиморфны. Так что произойдет следующее:

Animal.foo(); // prints Animal
Cat.foo(); // prints Cat

Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;

a.foo(); // should not be done. Prints Animal because the declared type of a is Animal
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat
d.foo(); // should not be done. Prints Animal because the declared type of d is Animal

Вызов статических методов на экземплярах, а не на классах - очень плохая практика, и никогда не следует делать это.

Сравните это с методами экземпляра, которые являются полиморфными и поэтому переопределяются. Вызываемый метод зависит от конкретного типа объекта во время выполнения:

public class Animal {
    public void foo() {
        System.out.println("Animal");
    }
}

public class Cat extends Animal {
    public void foo() { // overrides Animal.foo()
        System.out.println("Cat");
    }
}

Тогда произойдет следующее:

Animal a = new Animal();
Animal b = new Cat();
Animal c = new Cat();
Animal d = null;

a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException

Ответ 2

Прежде всего Что подразумевается под методом Hiding?

Метод скрытия означает, что подкласс определяет метод класса с той же сигнатурой, что и метод класса в суперклассе. В этом случае метод суперкласса скрыт подклассом. Это означает, что: Версия метода, который выполняется, НЕ будет определяться объектом, который используется для вызова. Фактически он будет определяться типом ссылочной переменной, используемой для вызова метода.

Что подразумевается под переопределением метода?

Подкласс класса переопределения метода определил метод экземпляра с тем же типом сигнатуры и возвращаемого типа (включая ковариантный тип) в качестве метода экземпляра в суперклассе. В этом случае метод суперкласса переопределяется (заменяется) подклассом. Это означает, что: Исполняемая версия метода будет определяться объектом, который используется для вызова. Он не будет определяться типом ссылочной переменной, используемой для вызова метода.

Почему статические методы нельзя переопределять?

Поскольку статические методы статически статичны (т.е. во время компиляции) на основе класса, на который они вызываются, а не динамически, как в случае с методами экземпляра, которые разрешены полиморфно на основе типа среды выполнения объекта.

Как следует обращаться к статическим методам?

Статические методы должны быть доступны статическим способом. то есть именем самого класса, а не использованием экземпляра.

Вот краткий демонстрационный пример для переопределения и скрытия метода:

class Super
{
  public static void foo(){System.out.println("I am foo in Super");}
  public void bar(){System.out.println("I am bar in Super");}
}
class Child extends Super
{
  public static void foo(){System.out.println("I am foo in Child");}//Hiding
  public void bar(){System.out.println("I am bar in Child");}//Overriding
  public static void main(String[] args)
  {
     Super sup = new Child();//Child object is reference by the variable of type Super
     Child child = new Child();//Child object is referenced by the variable of type Child
     sup.foo();//It will call the method of Super.
     child.foo();//It will call the method of Child.

     sup.bar();//It will call the method of Child.
     child.bar();//It will call the method of Child again.
  }
}

Выход -

I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child

Очевидно, как указано, поскольку foo - это метод класса, поэтому вызываемая версия foo будет определяться типом ссылочной переменной (например, Super или Child), ссылающейся на объект Child. Если на него ссылается переменная Super, то вызывается foo of Super. И если на него ссылается переменная Child, тогда вызывается foo of Child.
Принимая во внимание,
Поскольку bar - это метод экземпляра, поэтому вызываемая версия bar определяется исключительно объектом (i.e Child), который используется для его вызова. Независимо от того, через какую ссылочную переменную (Super или Child) она вызывается, метод, который будет вызываться, всегда имеет значение Child.

Ответ 3

Чтобы перезаписать, метод означает, что всякий раз, когда метод вызывается на объект производного класса, будет вызываться новая реализация.

Чтобы скрыть, метод означает, что неквалифицированный вызов этого имени в области этого класса (т.е. в теле любого из его методов или при наличии имени этого класса) теперь вызывается совершенно другая функция, требующая квалификации для доступа к статическому методу с тем же именем из родительского класса.

Подробнее Наследование Java: перезаписанные или скрытые методы

Ответ 4

Если подкласс определяет метод класса с той же сигнатурой, что и метод класса в суперклассе, метод в подклассе скрывает тот, что находится в суперклассе.

Скрытые методы в Статическом контексте, я считаю. Статические методы сами по себе не переопределяются, поскольку разрешение вызовов метода выполняется компилятором во время самого компиляции. Итак, если вы определяете статический метод в базовом классе с той же сигнатурой, что и в родительском классе, то метод в подклассе скрывает метод, унаследованный от суперкласса.

class Foo {
  public static void method() {
     System.out.println("in Foo");
  }
}

class Bar extends Foo {
   public static void method() {
    System.out.println("in Bar");
  }
}

Ответ 5

Например, вы можете переопределить методы экземпляра в суперклассе, но не статические.

Скрытие - это родительский класс имеет статический метод с именем Foo, а подкласс также имеет статический метод Foo.

Другой сценарий: родительский статический метод с именем Cat, а подкласс - метод экземпляра с именем Cat. (статические и экземпляры с одной и той же сигнатурой не могут смешиваться).

public class Animal {

  public static String getCat() { return "Cat"; }

  public boolean isAnimal() { return true; }
}

public class Dog extends Animal {

  // Method hiding
  public static String getCat() { }

  // Not method hiding
  @Override
  public boolean isAnimal() { return false; }
}

Ответ 6

 class P
    {
    public static  void m1()
    {
    System.out.println("Parent");
    }
}
    class C extends P
    {
    public static void m1()
    {
    System.out.println("Child");
    }
}
class Test{
    public static void main(String args[])
    {
    Parent p=new Parent();//Parent
    Child c=new Child();  //Child
    Parent p=new Child();  //Parent
    }
    }

If the both parent and child class method are static the compiler is responsible for method resolution based on reference type

class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent 
Child c=new Child();   //Child
Parent p=new Child();  //Child
}
}

If both method are not static  jvm is responsible for method resolution based on run time object