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

Джавадок говорит:

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

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

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 

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

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

 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 

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

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

Что означает переопределение метода?

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

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

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

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

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

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

 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 – это метод classа, поэтому версия вызванного foo будет определяться типом ссылочной переменной (например, Super или Child), ссылающейся на объект Child . Если на него ссылается Super переменная, то вызывается foo of Super . И если на нее ссылается переменная Child тогда вызывается foo of Child .
Принимая во внимание ,
Поскольку bar является методом экземпляра, поэтому версия вызываемого bar определяется исключительно объектом (т.е. Child ), который используется для его вызова. Независимо от того, через какую ссылочную переменную ( Super или Child ) она вызывается, метод, который будет вызываться, всегда имеет значение Child .

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

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

Дополнительная информация Java Inheritance: перезаписанные или скрытые методы

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

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

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

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

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

Другим сценарием является родительский статический метод с именем Cat, а подclass – метод экземпляра с именем 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; } } 
  • Почему Java Map не расширяет коллекцию?
  • Почему я должен использовать список инициализации членов?
  • Реферирование ссылочного типа - новая ссылочная переменная, созданная каждым циклом в цикле, если объявлена ​​в нем?
  • Почему мы не можем изменять модификатор доступа при переопределении методов в C #?
  • Основной код метода полностью внутри try / catch: это плохая практика?
  • Каковы различия между типами () и isinstance ()?
  • Как производный class может вызвать частный метод базового classа?
  • Замена if else с шаблоном
  • Свободные интерфейсы - Цепочка метода
  • Как вы получаете ссылку на class включения из анонимного внутреннего classа в Java?
  • Статические и экземпляры с тем же именем?
  • Давайте будем гением компьютера.