¿Los métodos estáticos se heredan en Java?

Estaba leyendo la Guía de un progtwigdor de certificación Java ™ SCJP por Khalid Mughal.

En el capítulo Herencia, explica que

La herencia de los miembros está estrechamente ligada a su accesibilidad declarada. Si se puede acceder a un miembro de una superclase por su nombre simple en la subclase (sin el uso de ninguna syntax adicional como super), ese miembro se considera heredado

También menciona que los métodos estáticos no son heredados. Pero el siguiente código está perfectamente bien:

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(); } } 

¿Cómo puedo usar directamente display() en la clase B ? Aún más, B.display() también funciona.

¿La explicación del libro solo se aplica a los métodos de instancia?

Todos los métodos que son accesibles son heredados por subclases.

De los tutoriales de Sun Java:

Una subclase hereda todos los miembros públicos y protegidos de su elemento primario, sin importar en qué paquete esté la subclase. Si la subclase está en el mismo paquete que su elemento primario, también hereda los miembros privados del paquete del elemento primario. Puede usar los miembros heredados tal como están, reemplazarlos, ocultarlos o complementarlos con nuevos miembros

La única diferencia con los métodos estáticos heredados (clase) y los métodos heredados no estáticos (instancia) es que cuando se escribe un nuevo método estático con la misma firma, el antiguo método estático simplemente se oculta, no se anula.

Desde la página sobre la diferencia entre anular y ocultar.

La distinción entre ocultar y anular tiene implicaciones importantes. La versión del método reemplazado que se invoca es la de la subclase. La versión del método oculto que se invoca depende de si se invoca desde la superclase o la subclase

Si eso es lo que el libro realmente dice, está mal. [1]

La especificación de lenguaje Java # 8.4.8 establece:

8.4.8 Herencia, anulación y ocultación

Una clase C hereda de su superclase directa todos los métodos concretos m (tanto estáticos como de instancia) de la superclase para la que se cumplen todas las condiciones siguientes:

  • m es un miembro de la superclase directa de C.

  • m es público, protegido o declarado con acceso a paquetes en el mismo paquete que C.

  • Ningún método declarado en C tiene una firma que es una subscripción (§8.4.2) de la firma de m.

[1] No dice eso en mi copia, 1ra edición, 2000.

Puede experimentar la diferencia en el siguiente código, que es una pequeña modificación de su código.

 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(); } } 

Esto se debe a que los métodos estáticos son métodos de clase.

A.display () y B.display () llamarán al método de sus respectivas clases.

B.display () funciona porque la statement estática hace que el método / miembro pertenezca a la clase, y no a ninguna instancia de clase en particular (también conocida como Objeto). Puedes leer más sobre esto aquí .

Otra cosa a tener en cuenta es que no puede anular un método estático, puede hacer que su subclase declare un método estático con la misma firma, pero su comportamiento puede ser diferente de lo que cabría esperar. Esta es probablemente la razón por la cual no se considera heredada. Puede consultar el escenario problemático y la explicación aquí .

Este concepto no es tan fácil como parece. Podemos acceder a miembros estáticos sin herencia, que es una relación HasA. Podemos acceder a miembros estáticos extendiendo también la clase principal. Eso no implica que se trate de una relación ISA (Herencia). En realidad, los miembros estáticos pertenecen a la clase y static no es un modificador de acceso. Siempre que los modificadores de acceso permitan acceder a los miembros estáticos, podemos usarlos en otras clases. Al igual que si es público, será accesible dentro del mismo paquete y también fuera del paquete. Para privado no podemos usarlo en ningún lado. Por defecto, podemos usarlo solo dentro del paquete. Pero para proteger tenemos que extender la súper clase. Por lo tanto, obtener el método estático en otra clase no depende de ser estático. Depende de los modificadores de acceso. Entonces, en mi opinión, los miembros estáticos pueden acceder si los modificadores de acceso lo permiten. De lo contrario, podemos usarlos como lo usamos por Hasa-relation. Y tiene una relación no es herencia. De nuevo, no podemos anular el método estático. Si podemos usar otro método pero no podemos anularlo, entonces es una relación HasA. Si no podemos anularlos, no será herencia. Así que el escritor fue 100% correcto.

Los métodos estáticos se heredan en Java pero no participan en el polymorphism. Si intentamos anular los métodos estáticos, simplemente ocultarán los métodos estáticos de la superclase en lugar de anularlos.

El método estático se hereda en la subclase pero no es polymorphism. Al escribir la implementación del método estático, el método de clase de los padres está sobre oculto, no anulado. Piensa, si no es heredado, cómo puedes acceder sin classname.staticMethodname(); ?

Todos los miembros públicos y protegidos se pueden heredar de cualquier clase, mientras que los miembros predeterminados o del paquete también se pueden heredar de la clase dentro del mismo paquete que el de la superclase. No depende si es un miembro estático o no estático.

Pero también es cierto que la función miembro estática no forma parte de la vinculación dinámica. Si la firma de ese método estático es la misma en las clases principal y secundaria, entonces se aplica el concepto de Sombreado, no polymorphism.

Puede anular los métodos estáticos, pero si intenta usar el polymorphism, entonces funcionan de acuerdo con el scope de clase (al contrario de lo que normalmente esperamos).

 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(); } } 

En el primer caso, o / p es el “método estático de B” # anulación exitosa En el segundo caso, o / p es “en método estático de A” # Método estático – no tendrá en cuenta el polymorphism

Muchos han expresado su respuesta en palabras. Esta es una explicación extendida en los códigos:

 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(); 

Resultados:

 A B Test Test A B Test Test A A 

Por lo tanto, esta es la conclusión:

  1. Cuando llamamos a la estática de una manera estática a través de., Buscará la estática definida en esa clase, o la clase más cercana a esa en la cadena de herencia. Esto demuestra que los métodos estáticos son heredados.
  2. Cuando se llama al método estático desde una instancia, llama al método estático definido en el tipo de tiempo de comstackción.
  3. El método estático se puede invocar desde una instancia null . Supongo que el comstackdor usará el tipo de variable para encontrar la clase durante la comstackción y la traducirá a la llamada al método estático correspondiente.

Los métodos estáticos en Java se heredan, pero no se pueden anular. Si declara el mismo método en una subclase, oculta el método de la superclase en lugar de anularlo. Los métodos estáticos no son polimórficos. En el momento de la comstackción, el método estático se vinculará estáticamente.

Ejemplo:

 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(); } } 

Obtendrás lo siguiente:

 Writing Writing Writing Writing book 

Podemos declarar métodos estáticos con la misma firma en la subclase, pero no se considera anulación, ya que no habrá ningún polymorphism en tiempo de ejecución. Debido a que todos los miembros estáticos de una clase se cargan en el momento de la carga de la clase, decide en comstackción tiempo (invalidación en tiempo de ejecución) Por lo tanto, la respuesta es ‘No’.

Los miembros estáticos son miembros universales. Se puede acceder desde cualquier lugar.

Los miembros estáticos no se heredarán en la subclase porque la herencia solo se aplica a los miembros no estáticos. Los cargadores de clases cargarán los miembros estáticos dentro del grupo estático. La herencia es solo para aquellos miembros que están cargados dentro del objeto