He estado jugando con modificadores con método estático y encontré un comportamiento extraño.
Como sabemos, los métodos estáticos no pueden anularse, ya que están asociados con la clase en lugar de la instancia.
Entonces, si tengo el fragmento de abajo, se compila bien
//Snippet 1 - Compiles fine
public class A {
static void ts() {
}
}
class B extends A {
static void ts() {
}
}
Pero si incluyo el modificador final al método estático en la clase A, la compilación falla ts () en B no puede anular ts () en A; El método reemplazado es estático final .
¿Por qué sucede esto cuando el método estático no se puede anular en absoluto?
Respuestas:
Los métodos estáticos no se pueden anular, pero se pueden ocultar. El
ts()
método de B no anula (no está sujeto a polimorfismo) elts()
de A pero lo ocultará. Si llamats()
a B (NOA.ts()
oB.ts()
... solots()
), se llamará a B y no a A. Dado que esto no está sujeto a polimorfismo, la llamadats()
en A nunca se redirigirá a la de B.La palabra clave
final
deshabilitará la ocultación del método. Por lo tanto, no se pueden ocultar y un intento de hacerlo generará un error de compilación.Espero que esto ayude.
fuente
A#ts
se está heredando y que tal método ya existeB
, simplemente tener dos métodos con la misma firma y un modificador diferente (final
) no funcionaría como sobrecargas. Sin embargo, desearía poder pensar en un mensaje simple para estoEsto no es exactamente cierto. El código de ejemplo realmente significa que el método ts en B oculta el método ts en A. Por lo tanto, no se anula exactamente. En Javaranch hay una buena explicación.
fuente
Los métodos estáticos pertenecen a la clase, no a la instancia.
A.ts()
yB.ts()
siempre serán métodos separados.El verdadero problema es que Java le permite llamar a métodos estáticos en un objeto de instancia. Los métodos estáticos con la misma firma de la clase padre se ocultan cuando se llama desde una instancia de la subclase. Sin embargo, no puede anular / ocultar los métodos finales .
Pensarías que el mensaje de error usaría la palabra oculta en lugar de anulada ...
fuente
Puede encontrarse en la posición de pensar en hacer un método estático final, considerando lo siguiente:
Tener las siguientes clases:
Ahora la forma 'correcta' de llamar a estos métodos sería
lo que resultaría en,
AB
pero también podría llamar a los métodos en instancias:lo que resultaría
AB
también.Ahora considere lo siguiente:
eso se imprimiría
A
. Eso podría sorprenderlo ya que en realidad está teniendo un objeto de claseB
. Pero como lo está llamando desde una referencia de tipoA
, llamaráA.ts()
. Puede imprimirB
con el siguiente código:En ambos casos, el objeto que tiene es en realidad de la clase
B
. Pero dependiendo del puntero que apunta al objeto, llamará al método desdeA
o desdeB
.Ahora digamos que usted es el desarrollador de la clase
A
y desea permitir la subclasificación. Pero realmente desea un métodots()
, siempre que se lo llame, incluso desde una subclase, que hace lo que quiere que haga y que no esté oculto por una versión de subclase. Entonces podría hacerlofinal
y evitar que se oculte en la subclase. Y puede estar seguro de que el siguiente código llamará al método desde su claseA
:Ok, admitidamente, eso está construido de alguna manera, pero podría tener sentido para algunos casos.
No debe llamar a métodos estáticos en instancias sino directamente en las clases, entonces no tendrá ese problema. También IntelliJ IDEA, por ejemplo, le mostrará una advertencia, si llama a un método estático en una instancia y también si hace que un método estático sea final.
fuente
El método ts () en B no anula el método ts () en A, simplemente es otro método. La clase B no ve el método ts () en A ya que es estático, por lo tanto, puede declarar su propio método llamado ts ().
Sin embargo, si el método es final, entonces el compilador detectará que hay un método ts () en A que no debe anularse en B.
fuente
Creo que el error de compilación fue bastante engañoso aquí. No debería haber dicho "el método reemplazado es estático final", sino que debería haber dicho "el método reemplazado es final". El modificador estático es irrelevante aquí.
fuente
Un método estático no se puede anular en Java, a diferencia de los métodos no estáticos. Pero se heredan como miembros de datos estáticos y no estáticos. Es por eso que no se puede crear un método no estático con el mismo nombre en la clase primaria
La
final
palabra clave asegura que el cuerpo del método específico se ejecute cada vez que se llame al método. Ahora, si se crea un método estático en la clase secundaria con el mismo nombre y se realiza una llamada al método, se ejecuta el método en la subclase, lo que no debería ser el caso si final es prefijado antes del nombre del método estático en la clase primaria . Por lo tanto, la palabra clave final restringe la creación de un método con el mismo nombre en la clase secundaria.fuente