Статические методы, унаследованные в Java?

Я читал "Руководство программистов" Сертификация Java ™ SCJP от Khalid Mughal.

В главе "Наследование" объясняется, что

Наследование членов тесно связано с их объявленными доступность. Если член суперкласса доступен по простому имени в подклассе (без использования какого-либо дополнительного синтаксиса, такого как 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().

Обоснование книги применимо только к методам экземпляра?

Ответ 1

Все доступные методы наследуются подклассами.

Из Sun Java Tutorials:

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

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

Со страницы о разнице между переопределением и сокрытием.

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

Ответ 2

Если это то, что действительно говорит книга, это неправильно. [1]

Спецификация языка Java # 8.4.8:

8.4.8 Наследование, переопределение и скрытие

Класс C наследует от своего прямого суперкласса все конкретные методы m (как статические, так и экземпляры) суперкласса, для которых все следующее верно:

  • m является членом прямого суперкласса C.

  • m является общедоступным, защищенным или объявленным с доступом к пакету в том же пакете, что и C.

  • Никакой метод, объявленный в C, не имеет подписи (подстрока) (§8.4.2) подписи m.

[1] Он не говорит, что в моей копии, 1-е издание, 2000.

Ответ 3

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

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() будут вызывать методы соответствующих классов.

Ответ 4

B.display() работает, потому что статическое объявление заставляет метод/член принадлежать классу, а не какой-либо конкретный экземпляр класса (aka Object). Вы можете прочитать об этом здесь.

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

Ответ 5

Эта концепция не так проста, как кажется. Мы можем получить доступ к статическим членам без наследования, что является отношением HasA. Мы можем получить доступ к статическим членам, также расширив родительский класс. Это не означает, что это отношение ISA (Наследование). Фактически статические члены принадлежат классу, а static не является модификатором доступа. Пока модификаторы доступа допускают доступ к статическим членам, мы можем использовать их в других классах. Например, если он является общедоступным, он будет доступен внутри того же пакета, а также вне пакета. Для частных мы не можем использовать его нигде. По умолчанию мы можем использовать его только внутри пакета. Но для защиты мы должны расширить суперкласс. Таким образом, статический метод для другого класса не зависит от статики. Это зависит от модификаторов доступа. Поэтому, на мой взгляд, члены Статики могут получить доступ, если разрешают модификаторы доступа. В противном случае мы можем использовать их так, как мы используем отношение Хаса. И имеет отношение не наследование. Опять же, мы не можем переопределить статический метод. Если мы можем использовать другой метод, но не можем его переопределить, то это отношение HasA. Если мы не сможем переопределить их, это не будет наследованием. Так что автор был на 100% прав.

Ответ 6

Статические методы наследуются на Java, но они не участвуют в полиморфизме. Если мы попытаемся переопределить статические методы, они просто скроют статические методы суперкласса вместо их переопределения.

Ответ 7

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

Но также верно, что статическая функция-член не участвует в динамической привязке. Если подпись этого статического метода одинакова как в родительском, так и в дочернем классе, тогда применяется понятие тени, а не полиморфизм.

Ответ 8

Статический метод наследуется в подклассе, но это не полиморфизм. Когда вы пишете реализацию статического метода, метод родительского класса скрывается, а не переопределяется. Подумайте, если он не унаследован, то как вы можете получить доступ без classname.staticMethodname();?

Ответ 9

Вы можете переопределить статические методы, но если вы попытаетесь использовать полиморфизм, то они работают в соответствии с классом (в отличие от того, что мы обычно ожидаем).

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" # Статический метод - не будет рассматривать полиморфизм

Ответ 10

Статические методы в 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

Ответ 11

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

Ответ 12

Многие из них высказали свой ответ словами. Это расширенное объяснение в кодах:

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

Поэтому это вывод:

  1. Когда мы ставим статический статический метод через., Он будет искать статическую информацию, определенную в этом классе, или ближайший к ней класс цепочки наследования. Это доказывает, что статические методы наследуются.
  2. Когда статический метод вызывается из экземпляра, он вызывает статический метод, определенный в типе времени компиляции.
  3. Статический метод можно вызвать из null экземпляра. Я предполагаю, что компилятор будет использовать тип переменной для поиска класса во время компиляции и перевести его на соответствующий вызов статического метода.

Ответ 13

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

Ответ 14

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