Наследуются ли статические методы в Java?
Я читал руководство Программиста По Сертификация 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()
тоже работает.
применимо ли объяснение книги только к методам экземпляра?
14 ответов
все доступные методы наследуются подклассами.
от Солнца Java уроки:
подкласс наследует все открытые и защищенные члены своего родителя, независимо от того, в каком пакете находится подкласс. Если подкласс находится в том же пакете, что и его родитель, он также наследует члены package-private родителя. Наследуемые элементы можно использовать как есть, заменять их, скрывать или дополнять новыми члены
единственное отличие от унаследованных статических (class) методов и унаследованных нестатических (instance) методов заключается в том, что при написании нового статического метода с той же сигнатурой старый статический метод просто скрыт, а не переопределен.
с страница о разнице между переопределением и скрытием.
различие между скрытием и переопределением имеет важные последствия. Версия переопределенного метода что вызывается в подклассе. Версия скрытого метода, который вызывается, зависит от того, вызывается ли он из суперкласса или подкласса
Если это то, что книга действительно говорит, это неправильно.[1]
на Спецификация Языка Java #8.4.8 гласит:
8.4.8 наследование, переопределение и сокрытие
класс C наследует от своего прямого суперкласса все конкретные методы m (как статические, так и экземплярные) суперкласса, для которого все следующее верно:
m является членом прямого суперкласса C.
м. public, protected или объявленная с выходом пакета в пакет С.
ни один метод, объявленный в C, не имеет подписи, которая является подсигнализацией (§8.4.2) подписи m.
[1] это не сказано в моей копии, 1-е издание, 2000.
вы можете испытать разницу в следующем коде, который немного изменяет ваш код.
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();
b.display();
A a = new B();
a.display();
}
}
это связано с тем, что статические методы являются методами класса.
A. display () и B. display () вызовут метод своих соответствующих классов.
B. display () работает, потому что статическое объявление делает метод/член принадлежащим классу, а не какому-либо конкретному экземпляру класса (aka Object). Вы можете прочитать больше об этом здесь.
еще одно замечание заключается в том, что вы не можете переопределить статический метод, вы можете объявить свой подкласс статическим методом с той же сигнатурой, но его поведение может отличаться от того, что вы ожидаете. Вероятно, именно по этой причине он не считается унаследованным. Вы можете проверьте проблемный сценарий и объяснение здесь.
эта концепция не так проста, как кажется. Мы можем получить доступ к статическим членам без наследования, который имеет отношения. Мы можем получить доступ к статическим членам, также расширив родительский класс. Это не означает, что это ISA-отношение (наследование). На самом деле статические члены принадлежат классу, а static не является модификатором доступа. Пока модификаторы доступа разрешают доступ к статическим членам, мы можем использовать их в других классах. Например, если он публичный, то он будет доступен внутри такой же пакет и также вне пакета. Для частных мы не можем использовать его нигде. По умолчанию мы можем использовать только внутри пакета. Но для защиты мы должны расширить супер класс. Таким образом, получение статического метода в другой класс не зависит от статичности. Это зависит от модификаторов доступа. Таким образом, на мой взгляд, статические члены могут получить доступ, если модификаторы доступа позволяют. В противном случае, мы можем использовать их, как мы используем по Хаса-связи. И имеет отношение не к наследованию. Снова мы не можем переопределить статический метод. Если мы можем использовать другой метод, но не можем его переопределить, то это hasa-relation. Если мы не сможем их отменить, это не будет наследством.Таким образом, автор был на 100% прав.
статические методы наследуются в Java, но они не участвуют в полиморфизме. Если мы попытаемся переопределить статические методы, они просто скроют статические методы суперкласса вместо их переопределения.
статический метод наследуется в подклассе, но это не полиморфизм. При написании реализации статического метода родительский метод класса является скрытым, а не переопределенным. Подумайте, если он не унаследован, то как вы можете получить доступ без classname.staticMethodname();
?
все открытые и защищенные члены могут быть унаследованы от любого класса, в то время как члены по умолчанию или пакета также могут быть унаследованы от класса в том же пакете, что и у суперкласса. Это не зависит от того, является ли он статическим или нестатическим членом.
но также верно, что статическая функция-член, не участвуют в динамической привязки. Если подпись этого статического метода одинакова как в Родительском, так и в дочернем классе, то применяется концепция затенения, а не полиморфизм.
вы можете переопределить статические методы, но если вы пытаетесь использовать полиморфизм, то они работают по области видимости класса(вопреки тому, что мы обычно ожидаем).
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" # успешное переопределение Во 2-м случае o / p находится "в статическом методе" # статический метод - не будет рассматривать полиморфизм
многие озвучили свой ответ в словах. Это расширенное объяснение в коде:
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();
результаты:
A
B
Test
Test
A
B
Test
Test
A
A
таким образом, это вывод:
- когда мы вызываем статику статическим способом через ., он будет искать статический, определенный в этом классе, или класс, ближайший к этому в цепочке наследования. Это доказывает, что статические методы наследуются.
- когда статический метод вызывается из экземпляра, он вызывает статический метод, определенный в типе compile-time.
- статический метод может быть вызван из
null
экземпляра. Я предполагаю, что компилятор будет использовать тип переменной, чтобы найти класс во время компиляции и перевести его в соответствующий вызов статического метода.
статические методы в 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();
}
}
вы получите следующее:
Writing
Writing
Writing
Writing book
мы можем объявить статические методы с той же сигнатурой в подклассе, но он не считается переопределяющим, поскольку не будет никакого полиморфизма во время выполнения.Поскольку все статические члены класса загружаются во время загрузки класса, он решает во время компиляции(переопределение во время выполнения), поэтому ответ "Нет".
статические члены не будут наследоваться подклассу, потому что наследование только для нестатических членов.. И статические члены будут загружены внутри статического пула загрузчиком класса. Наследование только для тех членов, которые загружаются внутри объекта