Я читал «Руководство программиста по сертификации Java ™ SCJP » Халида Могала .
В главе о наследовании объясняется, что
Наследование членов тесно связано с их заявленной доступностью. Если член суперкласса доступен по своему простому имени в подклассе (без использования какого-либо дополнительного синтаксиса, такого как super), этот член считается унаследованным
Также упоминается, что статические методы не наследуются. Но приведенный ниже код прекрасен:
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();
}
}
Как я могу напрямую использовать display()
в классе B
? Более того, B.display()
тоже работает.
Применимо ли объяснение в книге только к методам экземпляра?
java
inheritance
static
Алгоритмист
источник
источник
Ответы:
Все доступные методы наследуются подклассами.
От Sun Java Tutorials :
Единственное отличие от унаследованных статических (классовых) методов и унаследованных нестатических (экземпляров) методов состоит в том, что когда вы пишете новый статический метод с той же сигнатурой, старый статический метод просто скрывается, а не переопределяется.
Со страницы о разнице между переопределением и скрытием.
источник
Вы можете почувствовать разницу в следующем коде, который немного отличается от вашего кода.
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(); } }
Это связано с тем, что статические методы являются методами класса.
A.display () и B.display () будут вызывать методы своих соответствующих классов.
источник
Если это действительно то, что книга говорит, это неправильно. [1]
Спецификация языка Java # 8.4.8 гласит:
[1] Это не сказано в моем экземпляре, 1-е издание, 2000 г.
источник
B.display () работает, потому что статическое объявление делает метод / член принадлежащим классу, а не какому-либо конкретному экземпляру класса (он же Object). Вы можете прочитать об этом здесь .
Также следует отметить, что вы не можете переопределить статический метод, вы можете сделать так, чтобы ваш подкласс объявлял статический метод с той же сигнатурой, но его поведение может отличаться от ожидаемого. Вероятно, это причина, по которой он не считается унаследованным. Вы можете ознакомиться с проблемным сценарием и объяснением здесь .
источник
Статические методы в Java наследуются, но не могут быть переопределены. Если вы объявляете тот же метод в подклассе, вы скрываете метод суперкласса, а не переопределяете его. Статические методы не полиморфны. Во время компиляции статический метод будет статически связан.
Пример:
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(); } }
Вы получите следующее:
источник
Статические методы наследуются в Java, но не участвуют в полиморфизме. Если мы попытаемся переопределить статические методы, они просто скроют статические методы суперкласса вместо их переопределения.
источник
Эта концепция не так проста, как кажется. Мы можем получить доступ к статическим членам без наследования, которое является отношением HasA. Мы можем получить доступ к статическим членам, также расширив родительский класс. Это не означает, что это ISA-отношение (наследование). Фактически статические члены принадлежат классу, а статические не являются модификатором доступа. Пока модификаторы доступа разрешают доступ к статическим членам, мы можем использовать их в других классах. Например, если он общедоступный, он будет доступен внутри того же пакета, а также вне пакета. Для личного пользования мы не можем нигде использовать. По умолчанию мы можем использовать его только внутри пакета. Но для защиты мы должны расширить суперкласс. Таким образом, получение статического метода для другого класса не зависит от того, является ли он статическим. Это зависит от модификаторов доступа. Итак, на мой взгляд, Статические члены могут получить доступ, если модификаторы доступа позволяют. В противном случае мы можем использовать их так, как мы используем отношение Хаса. И имеет отношение не по наследству. Опять же, мы не можем переопределить статический метод. Если мы можем использовать другой метод, но не можем его переопределить, то это отношение HasA. Если мы не сможем их переопределить, это не будет наследованием, значит, автор был на 100% прав.
источник
Статический метод наследуется в подклассе, но это не полиморфизм. Когда вы пишете реализацию статического метода, метод родительского класса скрывается, а не переопределяется. Подумайте, если он не передается по наследству, то как можно получить доступ без него
classname.staticMethodname();
?источник
Все открытые и защищенные члены могут быть унаследованы от любого класса, в то время как члены по умолчанию или члены пакета также могут быть унаследованы от класса в том же пакете, что и суперкласс. Это не зависит от того, является ли он статическим или нестатическим членом.
Но верно также и то, что статические функции-члены не участвуют в динамической привязке. Если сигнатура этого статического метода одинакова как в родительском, так и в дочернем классе, тогда применяется концепция Shadowing, а не полиморфизм.
источник
Вы можете переопределить статические методы, но если вы попытаетесь использовать полиморфизм, они будут работать в соответствии с областью действия класса (вопреки тому, что мы обычно ожидаем).
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(); } }
В первом случае o / p является «статическим методом B» # успешное переопределение Во втором случае o / p является «статическим методом A» # Статический метод - полиморфизм не учитывается.
источник
Мы можем объявить статические методы с той же сигнатурой в подклассе, но это не считается переопределяющим, так как не будет никакого полиморфизма во время выполнения, потому что все статические члены класса загружаются во время загрузки класса, поэтому он решает при компиляции time (переопределение во время выполнения) Следовательно, ответ - «Нет».
источник
Многие выразили свой ответ словами. Это расширенное объяснение в кодах:
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();
Полученные результаты:
Отсюда вывод:
null
экземпляра. Я предполагаю, что компилятор будет использовать тип переменной, чтобы найти класс во время компиляции и преобразовать его в соответствующий вызов статического метода.источник
Статические члены - это универсальные члены. К ним можно получить доступ откуда угодно.
источник
Статические члены не будут унаследованы в подкласс, потому что наследование предназначено только для нестатических членов. И статические члены будут загружены в статический пул загрузчиком класса. Наследование возможно только для тех членов, которые загружены внутри объекта.
источник