¿Por qué Java no permite la anulación de métodos estáticos?

¿Por qué no es posible anular los métodos estáticos?

Si es posible, usa un ejemplo.

Anulación depende de tener una instancia de una clase. El punto del polymorphism es que puede subclasificar una clase y los objetos que implementan esas subclases tendrán diferentes comportamientos para los mismos métodos definidos en la superclase (y anulados en las subclases). Un método estático no está asociado con ninguna instancia de una clase, por lo que el concepto no es aplicable.

Hubo dos consideraciones que impulsaron el diseño de Java que impactaron esto. Uno era una preocupación con el rendimiento: se habían criticado a Smalltalk por ser demasiado lento (la recolección de basura y las llamadas polimórficas formaban parte de eso) y los creadores de Java estaban decididos a evitar eso. Otra fue la decisión de que el público objective para Java eran los desarrolladores de C ++. Hacer que los métodos estáticos funcionen de la forma en que lo hacen tiene el beneficio de la familiaridad para los progtwigdores de C ++ y también es muy rápido, porque no hay necesidad de esperar hasta el tiempo de ejecución para descubrir qué método utilizar.

Personalmente creo que esto es un defecto en el diseño de Java. Sí, sí, entiendo que los métodos no estáticos se adjuntan a una instancia, mientras que los métodos estáticos se adjuntan a una clase, etc. Aún así, tenga en cuenta el siguiente código:

 public class RegularEmployee { private BigDecimal salary; public void setSalary(BigDecimal salary) { this.salary = salary; } public static BigDecimal getBonusMultiplier() { return new BigDecimal(".02"); } public BigDecimal calculateBonus() { return salary.multiply(getBonusMultiplier()); } /* ... presumbly lots of other code ... */ } public class SpecialEmployee extends RegularEmployee { public static BigDecimal getBonusMultiplier() { return new BigDecimal(".03"); } } 

Este código no funcionará como es de esperar. A saber, SpecialEmployee’s obtiene un bono del 2% al igual que los empleados regulares. Pero si eliminas las “estáticas” s, entonces SpecialEmployee’s obtiene una bonificación del 3%.

(Es cierto que este ejemplo es un estilo de encoding deficiente en el sentido de que en la vida real es probable que desee que el multiplicador de bonificación esté en alguna base de datos en lugar de estar codificado. Pero eso es solo porque no quería atascar el ejemplo de código irrelevante al punto.)

Me parece bastante plausible que quiera hacer que getBonusMultiplier estético. Quizás desee poder mostrar el multiplicador de bonificación para todas las categorías de empleados, sin necesidad de tener una instancia de un empleado en cada categoría. ¿Cuál sería el objective de buscar instancias de ejemplo? ¿Qué sucede si estamos creando una nueva categoría de empleados y todavía no tenemos empleados asignados? Esto es bastante lógicamente una función estática.

Pero no funciona.

Y sí, sí, puedo pensar en varias formas de reescribir el código anterior para que funcione. Mi punto no es que cree un problema irresoluble, sino que crea una trampa para el progtwigdor incauto, porque el lenguaje no se comporta como creo que una persona razonable esperaría.

Quizás si traté de escribir un comstackdor para un lenguaje OOP, vería rápidamente por qué implementarlo para que las funciones estáticas puedan ser anuladas sería difícil o imposible.

O quizás hay una buena razón por la cual Java se comporta de esta manera. ¿Alguien puede señalar una ventaja de este comportamiento, alguna categoría de problema que se hace más fácil con esto? Quiero decir, no solo apunte a la especificación del lenguaje Java y diga “ver, esto está documentado cómo se comporta”. Yo sé eso. ¿Pero hay una buena razón por la que DEBE comportarse de esta manera? (Además de lo obvio “hacerlo funcionar bien era demasiado difícil” …)

Actualizar

@VicKirk: Si quiere decir que este es un “mal diseño” porque no se ajusta a la forma en que Java maneja la estática, mi respuesta es: “Bueno, por supuesto, claro”. Como dije en mi publicación original, no funciona. Pero si te refieres a que es un mal diseño en el sentido de que habría algo fundamentalmente erróneo en un lenguaje donde esto funcionó, es decir, donde la estática podría ser anulada al igual que las funciones virtuales, esto de alguna manera introduciría una ambigüedad o sería imposible implementar de manera eficiente o algo así, respondo: “¿Por qué? ¿Qué hay de malo con el concepto?”

Creo que el ejemplo que doy es algo muy natural que quiero hacer. Tengo una clase que tiene una función que no depende de ningún dato de instancia, y que muy razonablemente podría querer llamar independientemente de una instancia, así como querer llamar desde un método de instancia. ¿Por qué esto no debería funcionar? Me he encontrado con esta situación muchas veces a lo largo de los años. En la práctica lo soluciono haciendo que la función sea virtual, y luego creo un método estático cuyo único propósito en la vida es ser un método estático que pasa la llamada al método virtual con una instancia ficticia. Esa parece una manera muy indirecta de llegar allí.

La respuesta corta es: es completamente posible, pero Java no lo hace.

Aquí hay un código que ilustra el estado actual de las cosas en Java:

Archivo Base.java :

 package sp.trial; public class Base { static void printValue() { System.out.println(" Called static Base method."); } void nonStatPrintValue() { System.out.println(" Called non-static Base method."); } void nonLocalIndirectStatMethod() { System.out.println(" Non-static calls overridden(?) static:"); System.out.print(" "); this.printValue(); } } 

Archivo Child.java :

 package sp.trial; public class Child extends Base { static void printValue() { System.out.println(" Called static Child method."); } void nonStatPrintValue() { System.out.println(" Called non-static Child method."); } void localIndirectStatMethod() { System.out.println(" Non-static calls own static:"); System.out.print(" "); printValue(); } public static void main(String[] args) { System.out.println("Object: static type Base; runtime type Child:"); Base base = new Child(); base.printValue(); base.nonStatPrintValue(); System.out.println("Object: static type Child; runtime type Child:"); Child child = new Child(); child.printValue(); child.nonStatPrintValue(); System.out.println("Class: Child static call:"); Child.printValue(); System.out.println("Class: Base static call:"); Base.printValue(); System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:"); child.localIndirectStatMethod(); System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:"); child.nonLocalIndirectStatMethod(); } } 

Si ejecuta esto (lo hice en una Mac, desde Eclipse, usando Java 1.6) obtiene:

 Object: static type Base; runtime type Child. Called static Base method. Called non-static Child method. Object: static type Child; runtime type Child. Called static Child method. Called non-static Child method. Class: Child static call. Called static Child method. Class: Base static call. Called static Base method. Object: static/runtime type Child -- call static from non-static method of Child. Non-static calls own static. Called static Child method. Object: static/runtime type Child -- call static from non-static method of Base. Non-static calls overridden(?) static. Called static Base method. 

Aquí, los únicos casos que podrían ser una sorpresa (y de los cuales se trata la pregunta) parecen ser el primer caso:

“El tipo de tiempo de ejecución no se usa para determinar qué métodos estáticos se obj.staticMethod() , incluso cuando se llama con una instancia de objeto ( obj.staticMethod() )”.

y el último caso:

“Al llamar a un método estático desde dentro de un método de objeto de una clase, el método estático elegido es el accesible desde la propia clase y no desde la clase que define el tipo de tiempo de ejecución del objeto”.

Llamar con una instancia de objeto

La llamada estática se resuelve en tiempo de comstackción, mientras que una llamada a un método no estático se resuelve en tiempo de ejecución. Tenga en cuenta que, aunque los métodos estáticos se heredan (de los padres), no se anulan (por hijo). Esto podría ser una sorpresa si esperaba lo contrario.

Llamar desde dentro de un método de objeto

Las llamadas al método de objeto se resuelven utilizando el tipo de tiempo de ejecución, pero las llamadas al método estáticas ( clase ) se resuelven utilizando el tipo de tiempo de comstackción (declarado).

Cambiar las reglas

Para cambiar estas reglas, de modo que la última llamada en el ejemplo llamada Child.printValue() , las llamadas estáticas tengan que proporcionarse con un tipo en tiempo de ejecución, en lugar de que el comstackdor resuelva la llamada en tiempo de comstackción con la clase declarada del objeto (o contexto). Las llamadas estáticas podrían usar la jerarquía de tipos (dynamics) para resolver la llamada, tal como lo hacen las llamadas a métodos de objetos hoy en día.

Esto sería fácilmente factible (si cambiamos Java: -O), y no es del todo irrazonable, sin embargo, tiene algunas consideraciones interesantes.

La consideración principal es que debemos decidir qué llamadas a métodos estáticos deberían hacer esto.

Por el momento, Java tiene esta “peculiaridad” en el lenguaje por el cual las llamadas obj.staticMethod() son reemplazadas por llamadas a ObjectClass.staticMethod() (normalmente con una advertencia). [ Nota: ObjectClass es el tipo de obj tiempo de comstackción.] Estos serían buenos candidatos para sobrescribir de esta manera, tomando el tipo de obj tiempo de ejecución.

Si lo hiciéramos, haría que los cuerpos de los métodos fueran más difíciles de leer: las llamadas estáticas en una clase principal podrían ser dinámicamente “reencaminadas”. Para evitar esto, deberíamos llamar al método estático con un nombre de clase, y esto hace que las llamadas se resuelvan más claramente con la jerarquía de tipos en tiempo de comstackción (como ahora).

Las otras formas de invocar un método estático son más complicadas: this.staticMethod() debería significar lo mismo que obj.staticMethod() , tomando el tipo de tiempo de ejecución de this . Sin embargo, esto podría causar algunos dolores de cabeza con los progtwigs existentes, que llaman a métodos estáticos (aparentemente locales) sin decoración (que es posiblemente equivalente a this.method() ).

Entonces, ¿qué pasa con llamadas sin adornos staticMethod() ? Sugiero que hagan lo mismo que hoy, y usen el contexto de clase local para decidir qué hacer. De lo contrario, se produciría una gran confusión. Por supuesto, significa que el method() significaría this.method() si el method fuera no estático, y ThisClass.method() si el method fuera estático. Esta es otra fuente de confusión.

Otras Consideraciones

Si cambiamos este comportamiento (y realizamos llamadas estáticas potencialmente dinámicas no locales), probablemente querríamos revisar el significado de final , private y protected como calificadores en métodos static de una clase. Entonces, todos tendremos que acostumbrarnos al hecho de que private static métodos public final private static y public final no se anulan, y por lo tanto se pueden resolver de manera segura en tiempo de comstackción, y son “seguros” para leerlos como referencias locales.

En realidad, estábamos equivocados.
A pesar de que Java no le permite sobrescribir los métodos estáticos de manera predeterminada, si examina detenidamente la documentación de las clases Class y Method en Java, aún puede encontrar una manera de emular la eliminación de métodos estáticos siguiendo la siguiente solución:

 import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; class RegularEmployee { private BigDecimal salary = BigDecimal.ONE; public void setSalary(BigDecimal salary) { this.salary = salary; } public static BigDecimal getBonusMultiplier() { return new BigDecimal(".02"); } public BigDecimal calculateBonus() { return salary.multiply(this.getBonusMultiplier()); } public BigDecimal calculateOverridenBonus() { try { // System.out.println(this.getClass().getDeclaredMethod( // "getBonusMultiplier").toString()); try { return salary.multiply((BigDecimal) this.getClass() .getDeclaredMethod("getBonusMultiplier").invoke(this)); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } return null; } // ... presumbly lots of other code ... } final class SpecialEmployee extends RegularEmployee { public static BigDecimal getBonusMultiplier() { return new BigDecimal(".03"); } } public class StaticTestCoolMain { static public void main(String[] args) { RegularEmployee Alan = new RegularEmployee(); System.out.println(Alan.calculateBonus()); System.out.println(Alan.calculateOverridenBonus()); SpecialEmployee Bob = new SpecialEmployee(); System.out.println(Bob.calculateBonus()); System.out.println(Bob.calculateOverridenBonus()); } } 

Resultado resultante:

 0.02 0.02 0.02 0.03 

lo que estábamos tratando de lograr 🙂

Incluso si declaramos a Carl como Tercera variable como Empleado Regular y le asignamos la instancia de Empleado Especial, todavía tendremos la llamada del método EmpleadorPorInio en el primer caso y el método de llamada del EmpleadoEspecial en el segundo caso

 RegularEmployee Carl = new SpecialEmployee(); System.out.println(Carl.calculateBonus()); System.out.println(Carl.calculateOverridenBonus()); 

solo mira la consola de salida:

 0.02 0.03 

😉

Los métodos estáticos son tratados como globales por la JVM, no están vinculados a una instancia de objeto en absoluto.

Podría conceptualmente ser posible si pudiera llamar a métodos estáticos desde objetos de clase (como en idiomas como Smalltalk) pero no es el caso en Java.

EDITAR

Puedes sobrecargar el método estático, está bien. Pero no puede anular un método estático, porque la clase no es un objeto de primera clase. Puede usar reflection para obtener la clase de un objeto en tiempo de ejecución, pero el objeto que obtiene no es paralelo a la jerarquía de clases.

 class MyClass { ... } class MySubClass extends MyClass { ... } MyClass obj1 = new MyClass(); MySubClass obj2 = new MySubClass(); ob2 instanceof MyClass --> true Class clazz1 = obj1.getClass(); Class clazz2 = obj2.getClass(); clazz2 instanceof clazz1 --> false 

Puedes reflexionar sobre las clases, pero se detiene allí. No invoque un método estático utilizando clazz1.staticMethod() , pero utilizando MyClass.staticMethod() . Un método estático no está ligado a un objeto y, por lo tanto, no existe una noción de this ni un super en un método estático. Un método estático es una función global; como consecuencia, tampoco existe una noción de polymorphism y, por lo tanto, la anulación de método no tiene sentido.

Pero esto podría ser posible si MyClass fuera un objeto en tiempo de ejecución en el que invocas un método, como en Smalltalk (o tal vez JRuby como sugiere un comentario, pero no sé nada de JRuby).

Oh, sí … una cosa más. Puede invocar un método estático a través de un objeto obj1.staticMethod() pero ese azúcar realmente sintáctico para MyClass.staticMethod() y debe evitarse. Por lo general, genera una advertencia en el IDE moderno. No sé por qué permitieron este atajo.

La sobreescritura del método es posible gracias al envío dynamic , lo que significa que el tipo declarado de un objeto no determina su comportamiento, sino más bien su tipo de tiempo de ejecución:

 Animal lassie = new Dog(); lassie.speak(); // outputs "woof!" Animal kermit = new Frog(); kermit.speak(); // outputs "ribbit!" 

Aunque tanto lassie como kermit se declaran como objetos de tipo Animal , su comportamiento (método .speak() ) varía porque el envío dynamic solo .speak() el método llamado .speak() a una implementación en tiempo de ejecución, no en tiempo de comstackción.

Ahora, aquí es donde la palabra clave static comienza a tener sentido: la palabra “estática” es un antónimo de “dynamic”. Por lo tanto, la razón por la que no puede anular los métodos estáticos es porque no hay un envío dynamic en los miembros estáticos, ya que estática significa literalmente “no dinámica”. Si se distribuyen de forma dinámica (y, por lo tanto, podrían ser sustituidos), la palabra clave static simplemente ya no tendría sentido.

Sí. Prácticamente Java permite anular el método estático, y teóricamente no, si anulas un método estático en Java, se comstackrá y se ejecutará sin problemas, pero perderá el polymorphism, que es la propiedad básica de Java. Leerá en todas partes que no es posible probarse comstackndo y ejecutándose. obtendrás tu respuesta. por ejemplo, si tienes Animal de clase y un método estático come () y Anulas ese método estático en su Subclase, lo llamamos Perro. Entonces, cuando sea que asignes un objeto Dog a un Animal Reference y te pongas a comer () según Java Dog’s eat () debería haberse llamado pero en estático Overriding Animals ‘eat () se llamará.

 class Animal { public static void eat() { System.out.println("Animal Eating"); } } class Dog extends Animal{ public static void eat() { System.out.println("Dog Eating"); } } class Test { public static void main(String args[]) { Animal obj= new Dog();//Dog object in animal obj.eat(); //should call dog's eat but it didn't } } Output Animal Eating 

De acuerdo con el Principio de Polimorfismo de Java, la salida debería ser comerse un Dog Eating .
Pero el resultado fue diferente porque para admitir el polymorphism, Java usa la vinculación tardía, lo que significa que los métodos se invocan solo en el tiempo de ejecución, pero no en el caso de los métodos estáticos. En los métodos estáticos, el comstackdor llama a los métodos en tiempo de comstackción y no de tiempo de ejecución, por lo que obtenemos métodos de acuerdo con la referencia y no según el objeto una referencia que contenga por eso Puede decir Prácticamente admite sobreescritura estática pero teóricamente no lo hace ‘t.

En Java (y en muchos lenguajes de progtwigción orientada a objetos, pero no puedo hablar para nada, y algunos no tienen nada de estático), todos los métodos tienen una firma fija: los parámetros y los tipos. En un método virtual, el primer parámetro está implícito: una referencia al objeto en sí y cuando se llama desde dentro del objeto, el comstackdor lo agrega automáticamente.

No hay diferencia para los métodos estáticos, todavía tienen una firma fija. Sin embargo, al declarar el método estático, usted ha declarado explícitamente que el comstackdor no debe incluir el parámetro de objeto implícito al comienzo de esa firma. Por lo tanto, cualquier otro código que lo llame debe no debe intentar poner una referencia a un objeto en la stack . Si hiciera eso, entonces la ejecución del método no funcionaría ya que los parámetros estarían en el lugar equivocado, desplazados por uno, en la stack.

Debido a esta diferencia entre los dos; los métodos virtuales siempre tienen una referencia al objeto de contexto (es decir, this ) por lo que es posible hacer referencia a cualquier elemento dentro del montón que pertenezca a esa instancia del objeto. Pero con los métodos estáticos, dado que no se pasa referencia, ese método no puede acceder a ninguna variable y método de objeto, ya que no se conoce el contexto.

Si desea que Java cambie la definición de manera que se transfiera un contexto de objeto para cada método, estático o virtual, entonces, en esencia, solo tendría métodos virtuales.

Cuando alguien preguntó en un comentario al operador, ¿cuál es su motivo y propósito para querer esta función?

No sé mucho sobre Ruby, ya que esto fue mencionado por el OP, investigué un poco. Veo que las clases de Ruby son realmente un tipo especial de objeto y uno puede crear (incluso dinámicamente) nuevos métodos. Las clases son objetos de clase completa en Ruby, no están en Java. Esto es algo que tendrá que aceptar cuando trabaje con Java (o C #). Estos no son lenguajes dynamics, aunque C # está agregando algunas formas de dinámica. En realidad, Ruby no tiene métodos “estáticos” por lo que pude encontrar; en ese caso, estos son métodos en el objeto de clase singleton. A continuación, puede anular este singleton con una nueva clase y los métodos en el objeto de clase anterior llamarán a los definidos en la nueva clase (¿correcto?). Por lo tanto, si llamaras a un método en el contexto de la clase original, solo ejecutaría las estadísticas estáticas originales, pero llamar a un método en la clase derivada llamaría a los métodos desde la clase principal o subclase. Interesante y puedo ver algo de valor en eso. Toma un patrón de pensamiento diferente.

Como trabaja en Java, tendrá que adaptarse a esa forma de hacer las cosas. ¿Por qué hicieron esto? Bueno, probablemente para mejorar el rendimiento en ese momento en función de la tecnología y la comprensión disponibles. Los lenguajes de computadora están en constante evolución. Regresa lo suficiente y no hay nada como OOP. En el futuro, habrá otras ideas nuevas.

EDIT : otro comentario. Ahora que veo las diferencias y, como desarrollador de Java / C #, puedo entender por qué las respuestas que obtienes de los desarrolladores de Java pueden ser confusas si vienes de un idioma como Ruby. Los métodos static Java no son lo mismo que class métodos de la class Ruby. Los desarrolladores de Java tendrán dificultades para entender esto, al igual que aquellos que trabajan principalmente con un lenguaje como Ruby / Smalltalk. Puedo ver cómo esto también sería muy confuso por el hecho de que Java también usa el “método de clase” como otra forma de hablar sobre métodos estáticos, pero este mismo término se usa de forma diferente por Ruby. Java no tiene métodos de clase de estilo Ruby (lo siento); Ruby no tiene métodos estáticos de estilo Java que son realmente antiguas funciones de estilo de procedimiento, como se encuentra en C.

Por cierto, ¡gracias por la pregunta! Hoy aprendí algo nuevo sobre los métodos de clase (estilo Ruby).

Bueno … la respuesta es NO si piensas desde la perspectiva de cómo debería comportarse un método modificado en Java. Pero no obtendrá ningún error de comstackción si intenta anular un método estático. Eso significa que, si intentas anular, Java no te impide hacerlo; pero ciertamente no obtienes el mismo efecto que obtienes por métodos no estáticos. Anulación en Java simplemente significa que el método particular se invocará en función del tipo de tiempo de ejecución del objeto y no en el tipo de tiempo de comstackción del mismo (que es el caso con los métodos estáticos anulados). De acuerdo … ¿adivina por qué se comportan de manera extraña? Debido a que son métodos de clase y, por lo tanto, el acceso a ellos siempre se resuelve durante el tiempo de comstackción utilizando la información del tipo de tiempo de comstackción. Acceder a ellos usando referencias de objetos es solo una libertad extra dada por los diseñadores de Java y ciertamente no deberíamos pensar en detener esa práctica solo cuando la restrinjan 🙂

Ejemplo : intentemos ver qué pasa si intentamos sobrescribir un método estático:

 class SuperClass { // ...... public static void staticMethod() { System.out.println("SuperClass: inside staticMethod"); } // ...... } public class SubClass extends SuperClass { // ...... // overriding the static method public static void staticMethod() { System.out.println("SubClass: inside staticMethod"); } // ...... public static void main(String[] args) { // ...... SuperClass superClassWithSuperCons = new SuperClass(); SuperClass superClassWithSubCons = new SubClass(); SubClass subClassWithSubCons = new SubClass(); superClassWithSuperCons.staticMethod(); superClassWithSubCons.staticMethod(); subClassWithSubCons.staticMethod(); // ... } } 

Salida : –
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

Observe la segunda línea de la salida. Si se hubiera reemplazado el método staticMethod, esta línea debería haber sido idéntica a la tercera línea, ya que invocamos el método staticMethod () en un objeto de Runtime Type como ‘SubClass’ y no como ‘SuperClass’. Esto confirma que los métodos estáticos siempre se resuelven usando su información de tipo de tiempo de comstackción únicamente.

En general, no tiene sentido permitir la ‘anulación’ de los métodos estáticos ya que no habría una buena manera de determinar a cuál llamar en tiempo de ejecución. Tomando el ejemplo de Empleado, si llamamos a RegularEmployee.getBonusMultiplier () – ¿qué método se supone que debe ejecutarse?

En el caso de Java, uno podría imaginar una definición de lenguaje donde es posible ‘sobrescribir’ los métodos estáticos siempre que se invoquen a través de una instancia de objeto. Sin embargo, todo lo que esto haría es volver a implementar los métodos de clase regulares, agregando redundancia al lenguaje sin realmente agregar ningún beneficio.

anulación está reservada para miembros de instancia para soportar el comportamiento polimórfico. los miembros de clase estáticos no pertenecen a una instancia particular. en su lugar, los miembros estáticos pertenecen a la clase y, como resultado, la anulación no se admite porque las subclases solo heredan los miembros protegidos y públicos de la instancia y no los miembros estáticos. You may want to define an inerface and research factory and/or strategy design patterns to evaluate an alternate approach.

I like and double Jay’s comment ( https://stackoverflow.com/a/2223803/1517187 ).
I agree that this is the bad design of Java.
Many other languages support overriding static methods, as we see in previous comments. I feel Jay has also come to Java from Delphi like me.
Delphi (Object Pascal) was the first language implementing OOP.
It is obvious that many people had experience with that language since it was in the past the only language to write commercial GUI products. And – yes, we could in Delphi override static methods. Actually, static methods in Delphi are called “class methods”, while Delphi had the different concept of “Delphi static methods” which were methods with early binding. To override methods you had to use late binding, declare “virtual” directive. So it was very convenient and intuitive and I would expect this in Java.

By overriding we can create a polymorphic nature depending on the object type. Static method has no relation with object. So java can not support static method overriding.

Answer of this question is simple, the method or variable marked as static belongs to the class only, So that static method cannot be inherited in the sub class because they belong to the super class only.

Overriding in Java simply means that the particular method would be called based on the runtime type of the object and not on the compile-time type of it (which is the case with overridden static methods). As static methods are class methods they are not instance methods so they have nothing to do with the fact which reference is pointing to which Object or instance, because due to the nature of static method it belongs to a specific class. You can redeclare it in the subclass but that subclass won’t know anything about the parent class’ static methods because, as I said, it is specific to only that class in which it has been declared. Accessing them using object references is just an extra liberty given by the designers of Java and we should certainly not think of stopping that practice only when they restrict it more details and example http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html

What good will it do to override static methods. You cannot call static methods through an instance.

 MyClass.static1() MySubClass.static1() // If you overrode, you have to call it through MySubClass anyway. 

EDIT : It appears that through an unfortunate oversight in language design, you can call static methods through an instance. Generally nobody does that. Mi error.

Easy solution: Use singleton instance. It will allow overrides and inheritance.

In my system, I have SingletonsRegistry class, which returns instance for passed Class. If instance is not found, it is created.

Haxe language class:

 package rflib.common.utils; import haxe.ds.ObjectMap; class SingletonsRegistry { public static var instances:Map, Dynamic>; static function __init__() { StaticsInitializer.addCallback(SingletonsRegistry, function() { instances = null; }); } public static function getInstance(cls:Class, ?args:Array) { if (instances == null) { instances = untyped new ObjectMap(); } if (!instances.exists(cls)) { if (args == null) args = []; instances.set(cls, Type.createInstance(cls, args)); } return instances.get(cls); } public static function validate(inst:Dynamic, cls:Class) { if (instances == null) return; var inst2 = instances[cls]; if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!"; } } 

A Static method, variable, block or nested class belongs to the entire class rather than an object.

A Method in Java is used to expose the behaviour of an Object / Class. Here, as the method is static (ie, static method is used to represent the behaviour of a class only.) changing/ overriding the behaviour of entire class will violate the phenomenon of one of the fundamental pillar of Object oriented programming ie, high cohesion . (remember a constructor is a special kind of method in Java.)

High Cohesion – One class should have only one role. For example: A car class should produce only car objects and not bike, trucks, planes etc. But the Car class may have some features(behaviour) that belongs to itself only.

Therefore, while designing the java programming language. The language designers thought to allow developers to keep some behaviours of a class to itself only by making a method static in nature.


The below piece code tries to override the static method, but will not encounter any comstacktion error.

 public class Vehicle { static int VIN; public static int getVehileNumber() { return VIN; }} class Car extends Vehicle { static int carNumber; public static int getVehileNumber() { return carNumber; }} 

This is because, here we are not overriding a method but we are just re-declaring it. Java allows re-declaration of a method (static/non-static).

Removing the static keyword from getVehileNumber() method of Car class will result into comstacktion error, Since, we are trying to change the functionality of static method which belongs to Vehicle class only.

Also, If the getVehileNumber() is declared as final then the code will not compile, Since the final keyword restricts the programmer from re-declaring the method.

 public static final int getVehileNumber() { return VIN; } 

Overall, this is upto software designers for where to use the static methods. I personally prefer to use static methods to perform some actions without creating any instance of a class. Secondly, to hide the behaviour of a class from outside world.

Here is a simple explanation. A static method is associated with a class while an instance method is associated with a particular object. Overrides allow calling the different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but the class itself in the first place. So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.

By overriding, you achieve dynamic polymorphism. When you say overriding static methods, the words you are trying to use are contradictory.

Static says – compile time, overriding is used for dynamic polymorphism. Both are opposite in nature, and hence can’t be used together.

Dynamic polymorphic behavior comes when a programmer uses an object and accessing an instance method. JRE will map different instance methods of different classes based on what kind of object you are using.

When you say overriding static methods, static methods we will access by using the class name, which will be linked at compile time, so there is no concept of linking methods at runtime with static methods. So the term “overriding” static methods itself doesn’t make any meaning.

Note: even if you access a class method with an object, still java compiler is intelligent enough to find it out, and will do static linking.

Now seeing above answers everyone knows that we can’t override static methods, but one should not misunderstood about the concept of accessing static methods from subclass .

We can access static methods of super class with subclass reference if this static method has not been hidden by new static method defined in sub class.

For Example, see below code:-

 public class StaticMethodsHiding { public static void main(String[] args) { SubClass.hello(); } } class SuperClass { static void hello(){ System.out.println("SuperClass saying Hello"); } } class SubClass extends SuperClass { // static void hello() { // System.out.println("SubClass Hello"); // } } 

Output:-

 SuperClass saying Hello 

See Java oracle docs and search for What You Can Do in a Subclass for details about hiding of static methods in sub class.

Gracias

The following code shows that it is possible:

 class OverridenStaticMeth { static void printValue() { System.out.println("Overriden Meth"); } } public class OverrideStaticMeth extends OverridenStaticMeth { static void printValue() { System.out.println("Overriding Meth"); } public static void main(String[] args) { OverridenStaticMeth osm = new OverrideStaticMeth(); osm.printValue(); System.out.println("now, from main"); printValue(); } }