Pourquoi Java ne permet-il pas de remplacer les méthodes statiques?

Pourquoi n’est-il pas possible de remplacer les méthodes statiques?

Si possible, veuillez utiliser un exemple.

    La substitution dépend de l’instance d’une classe. Le sharepoint polymorphism est que vous pouvez sous-classer une classe et que les objects qui implémentent ces sous-classes auront des comportements différents pour les mêmes méthodes définies dans la super-classe (et remplacées dans les sous-classes). Une méthode statique n’est associée à aucune instance d’une classe, le concept n’est donc pas applicable.

    Deux considérations ont influencé la conception de Java. L’un était un souci de performance: il y avait eu beaucoup de critiques de Smalltalk à propos de sa lenteur (la collecte des ordures et les appels polymorphes en faisaient partie) et les créateurs de Java étaient déterminés à éviter cela. Un autre était la décision que le public cible pour Java était les développeurs C ++. Faire fonctionner les méthodes statiques comme elles le faisaient avait l’avantage d’être familier pour les programmeurs C ++ et était également très rapide, car il n’est pas nécessaire d’attendre l’exécution pour déterminer la méthode à utiliser.

    Personnellement, je pense que c’est une faille dans la conception de Java. Oui, oui, je comprends que les méthodes non statiques sont attachées à une instance alors que les méthodes statiques sont attachées à une classe, etc. Et bien, considérez le code suivant:

     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()); } /* ... presumably lots of other code ... */ } public class SpecialEmployee extends RegularEmployee { public static BigDecimal getBonusMultiplier() { return new BigDecimal(".03"); } } 

    Ce code ne fonctionnera pas comme prévu. À savoir, SpecialEmployee reçoit un bonus de 2%, tout comme les employés réguliers. Mais si vous supprimez les “statiques”, alors SpecialEmployee recevra un bonus de 3%.

    (Certes, cet exemple est un style de codage médiocre, car dans la vraie vie, vous voudrez probablement que le multiplicateur de bonus se trouve dans une firebase database plutôt que codé en dur. Mais ce n’est que parce que je ne voulais pas de code sans rapport avec le point.)

    Il me semble tout à fait plausible que vous souhaitiez rendre getBonusMultiplier statique. Vous souhaitez peut-être afficher le multiplicateur de bonus pour toutes les catégories d’employés, sans devoir avoir une instance d’un employé dans chaque catégorie. Quel serait l’intérêt de rechercher de tels exemples? Que se passe-t-il si nous créons une nouvelle catégorie d’employés et que nous n’avons pas encore d’employés? C’est logiquement une fonction statique.

    Mais ça ne marche pas.

    Et oui, oui, je peux penser à un certain nombre de façons de réécrire le code ci-dessus pour le faire fonctionner. Ce que je veux dire, c’est que cela ne crée pas un problème insoluble, mais qu’il crée un piège pour le programmeur imprudent, car le langage ne se comporte pas comme une personne raisonnable le pense.

    Peut-être que si j’essayais d’écrire un compilateur pour un langage OOP, je verrais rapidement pourquoi l’implémenter pour que les fonctions statiques puissent être remplacées serait difficile ou impossible.

    Ou peut-être qu’il y a une bonne raison pour laquelle Java se comporte de cette façon. Quelqu’un peut-il signaler un avantage à ce comportement, une catégorie de problème qui est facilitée par cela? Je veux dire, ne me pointez pas vers les spécifications du langage Java et dites “voyez, ceci est documenté comment il se comporte”. Je le sais. Mais y a-t-il une bonne raison pour laquelle il devrait se comporter de la sorte? (En plus de l’évidence “le faire fonctionner correctement était trop difficile” …)

    Mettre à jour

    @VicKirk: Si vous voulez dire qu’il s’agit d’une “mauvaise conception” car elle ne correspond pas à la manière dont Java gère les statistiques, je réponds “Bien sûr, bien sûr”. Comme je l’ai dit dans mon message original, cela ne fonctionne pas. Mais si vous voulez dire qu’il s’agit d’une mauvaise conception en ce sens qu’il y aurait quelque chose de fondamentalement erroné dans un langage où cela fonctionnait, c’est-à-dire mettre en œuvre efficacement ou certains de ceux-ci, je réponds: “Pourquoi? Quel est le problème avec le concept?”

    Je pense que l’exemple que je donne est très naturel. J’ai une classe qui a une fonction qui ne dépend d’aucune donnée d’instance et que je pourrais très raisonnablement vouloir appeler indépendamment d’une instance, ainsi que vouloir appeler depuis une méthode d’instance. Pourquoi cela ne devrait-il pas fonctionner? J’ai rencontré cette situation un bon nombre de fois au cours des années. En pratique, je contourne le problème en rendant la fonction virtuelle, puis en créant une méthode statique dont le seul but dans la vie est d’être une méthode statique qui transmet l’appel à la méthode virtuelle avec une instance fictive. Cela semble être une façon très détournée d’y arriver.

    La réponse courte est: c’est tout à fait possible, mais Java ne le fait pas.

    Voici un code qui illustre l’ état actuel des choses en Java:

    Fichier Base.java :

     package sp.sortingal; 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(); } } 

    Fichier Child.java :

     package sp.sortingal; 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(Ssortingng[] 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 vous exécutez ceci (je l’ai fait sur un Mac, à partir d’Eclipse, en utilisant Java 1.6), vous obtenez:

     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. 

    Ici, les seuls cas qui pourraient être une surprise (et dont il s’agit de la question) semblent être le premier cas:

    “Le type d’exécution n’est pas utilisé pour déterminer quelles méthodes statiques sont appelées, même lorsqu’elles sont appelées avec une instance d’object ( obj.staticMethod() ).”

    et le dernier cas:

    “Lors de l’appel d’une méthode statique à partir d’une méthode object d’une classe, la méthode statique choisie est celle accessible à partir de la classe elle-même et non à partir de la classe définissant le type d’exécution de l’object.”

    Appel avec une instance d’object

    L’appel statique est résolu à la compilation, tandis qu’un appel de méthode non statique est résolu au moment de l’exécution. Notez que bien que les méthodes statiques soient héritées (de parent), elles ne sont pas remplacées (par enfant). Cela pourrait être une surprise si vous vous attendiez à autre chose.

    Appel depuis une méthode object

    Les appels de méthode object sont résolus à l’aide du type au moment de l’exécution, mais les appels de méthode statique ( classe ) sont résolus à l’aide du type de compilation (déclaré).

    Changer les règles

    Pour modifier ces règles, de sorte que le dernier appel de l’exemple appelé Child.printValue() , les appels statiques doivent être fournis avec un type au moment de l’exécution, plutôt que le compilateur résolvant l’appel à la compilation avec la classe déclarée de l’object (ou du contexte). Les appels statiques pourraient alors utiliser la hiérarchie de type (dynamic) pour résoudre l’appel, comme le font aujourd’hui les appels de méthode d’object.

    Cela serait facilement faisable (si nous changions Java: -O), et n’était pas du tout déraisonnable, cependant, cela a des considérations intéressantes.

    La principale considération est que nous devons décider quels appels de méthode statique doivent faire cela.

    À l’heure actuelle, Java a cette “bizarrerie” dans le langage par lequel les obj.staticMethod() sont remplacés par des ObjectClass.staticMethod() (normalement avec un avertissement). [ Note: ObjectClass est le type d’ obj de la compilation.] Ce sont de bons candidats pour se substituer de cette manière, en prenant le type d’exécution d’ obj .

    Si nous le faisions, cela rendrait les corps de méthode plus difficiles à lire: les appels statiques dans une classe parente pourraient potentiellement être “ré-acheminés” dynamicment . Pour éviter cela, il faudrait appeler la méthode statique avec un nom de classe – et cela rend les appels plus clairement résolus avec la hiérarchie de type à la compilation (comme maintenant).

    Les autres manières d’appeler une méthode statique sont plus compliquées: this.staticMethod() devrait signifier la même chose que obj.staticMethod() , en prenant le type d’exécution de this . Cependant, cela peut causer des problèmes avec les programmes existants, qui appellent des méthodes statiques (apparemment locales) sans décoration (ce qui est sans doute équivalent à this.method() ).

    Alors qu’en est-il des appels sans fioritures staticMethod() ? Je suggère qu’ils fassent la même chose qu’aujourd’hui et utilisent le contexte de classe local pour décider quoi faire. Sinon, une grande confusion s’ensuivrait. Bien sûr, cela signifie que method() signifierait this.method() si la method était une method non statique, et ThisClass.method() si la method était une méthode statique. Ceci est une autre source de confusion.

    Autres considérations

    Si nous changions ce comportement (et effectuions des appels statiques potentiellement dynamicment non-locaux), nous voudrions probablement revoir la signification de final , private et protected comme qualificateurs sur static méthodes static d’une classe. Nous devrions alors tous nous habituer au fait que private static méthodes public final private static et public final ne sont pas remplacées, et peuvent donc être résolues en toute sécurité à la compilation, et sont “sûres” à lire en tant que références locales.

    En fait, nous avions tort.
    Bien que Java ne vous permette pas de remplacer les méthodes statiques par défaut, si vous examinez attentivement la documentation des classes Class et Method en Java, vous pouvez toujours trouver un moyen d’émuler les méthodes statiques en remplaçant la solution suivante:

     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").toSsortingng()); 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; } // ... presumably lots of other code ... } final class SpecialEmployee extends RegularEmployee { public static BigDecimal getBonusMultiplier() { return new BigDecimal(".03"); } } public class StaticTestCoolMain { static public void main(Ssortingng[] 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()); } } 

    Résultat résultant:

     0.02 0.02 0.02 0.03 

    ce que nous essayions de réaliser 🙂

    Même si nous déclarons la troisième variable Carl en tant que RegularEmployee et que nous lui affectons l’instance de SpecialEmployee, nous aurons toujours l’appel de la méthode RegularEmployee dans le premier cas et l’appel de la méthode SpecialEmployee dans le second cas.

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

    il suffit de regarder la console de sortie:

     0.02 0.03 

    😉

    Les méthodes statiques sont traitées comme globales par la machine virtuelle Java, elles ne sont pas liées à une instance d’object.

    Cela pourrait être conceptuellement possible si vous pouviez appeler des méthodes statiques à partir d’objects de classe (comme dans des langages tels que Smalltalk), mais ce n’est pas le cas en Java.

    MODIFIER

    Vous pouvez surcharger la méthode statique, ça va. Mais vous ne pouvez pas remplacer une méthode statique, car la classe n’est pas un object de première classe. Vous pouvez utiliser la reflection pour obtenir la classe d’un object au moment de l’exécution, mais l’object que vous obtenez ne correspond pas à la hiérarchie des classes.

     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 

    Vous pouvez réfléchir sur les cours, mais ça s’arrête là. Vous clazz1.staticMethod() pas une méthode statique en utilisant clazz1.staticMethod() , mais en utilisant MyClass.staticMethod() . Une méthode statique n’est pas liée à un object et il n’y a donc pas de notion de this ni de super dans une méthode statique. Une méthode statique est une fonction globale. par conséquent, il n’y a pas non plus de notion de polymorphism et, par conséquent, le dépassement de méthode n’a aucun sens.

    Mais cela pourrait être possible si MyClass était un object à l’exécution sur lequel vous appelez une méthode, comme dans Smalltalk (ou peut-être JRuby comme le suggère un commentaire, mais je ne sais rien de JRuby).

    Oh oui … encore une chose. Vous pouvez appeler une méthode statique via un object obj1.staticMethod() mais ce sucre vraiment syntaxique pour MyClass.staticMethod() doit être évité. Il déclenche généralement un avertissement dans l’IDE moderne. Je ne sais pas pourquoi ils ont autorisé ce raccourci.

    La substitution de méthode est rendue possible par la dissortingbution dynamic , ce qui signifie que le type déclaré d’un object ne détermine pas son comportement, mais plutôt son type d’exécution:

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

    Même si lassie et kermit sont déclarés comme des objects de type Animal , leur comportement (méthode .speak() ) varie car la dissortingbution dynamic ne liera l’appel de la méthode .speak() qu’à une implémentation au moment de l’exécution et non à la compilation.

    Maintenant, voici où le mot-clé static commence à avoir un sens: le mot “statique” est un antonyme de “dynamic”. Donc, la raison pour laquelle vous ne pouvez pas remplacer les méthodes statiques est qu’il n’ya pas de répartition dynamic sur les membres statiques, car le terme statique signifie littéralement «non dynamic». Si elles sont envoyées dynamicment (et peuvent donc être surchargées), le mot-clé static n’aurait plus de sens.

    Oui. Pratiquement, Java autorise la méthode statique, et théoriquement, si vous remplacez une méthode statique en Java, il comstackra et fonctionnera sans problème, mais perdra le polymorphism qui est la propriété de base de Java. Vous allez lire Partout qu’il n’est pas possible de vous essayer à la compilation et à l’exécution. vous aurez votre réponse. Par exemple, si vous avez Class Animal et une méthode statique eat () et que vous remplacez cette méthode statique dans sa sous-classe, elle s’appelle Dog. Alors, où que vous affectiez un object Chien à une Référence Animale et que vous appeliez Manger () selon Java, Manger () aurait dû être appelé, mais en statique, Dégager () sera appelé.

     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(Ssortingng args[]) { Animal obj= new Dog();//Dog object in animal obj.eat(); //should call dog's eat but it didn't } } Output Animal Eating 

    Selon le principe de polymorphism de Java, le résultat devrait être Dog Eating .
    Mais le résultat était différent car, pour prendre en charge Polymorphism, Java utilise Late Binding, ce qui signifie que les méthodes ne sont appelées qu’au moment de l’exécution, mais pas dans le cas des méthodes statiques. Dans les méthodes statiques, le compilateur appelle des méthodes au moment de la compilation plutôt que de l’exécution, donc nous obtenons des méthodes en fonction de la référence et non pas une référence à un contenant qui explique pourquoi il supporte statique mais théoriquement, il ne ‘t.

    En Java (et dans de nombreux langages de la POO, mais je ne peux pas parler pour tout le monde, et certains ne sont pas du tout statiques), toutes les méthodes ont une signature fixe – les parameters et les types. Dans une méthode virtuelle, le premier paramètre est implicite: une référence à l’object lui-même et lorsqu’il est appelé depuis l’object, le compilateur l’ajoute automatiquement.

    Il n’y a pas de différence pour les méthodes statiques – elles ont toujours une signature fixe. Cependant, en déclarant la méthode static, vous avez explicitement déclaré que le compilateur ne doit pas inclure le paramètre d’object implicite au début de cette signature. Par conséquent, tout autre code qui appelle cela ne doit pas tenter de placer une référence à un object sur la stack . Si c’était le cas, alors l’exécution de la méthode ne fonctionnerait pas car les parameters seraient au mauvais endroit – décalés de un – sur la stack.

    A cause de cette différence entre les deux Les méthodes virtuelles ont toujours une référence à l’object contextuel (c.-à this d. this ), il est donc possible de référencer n’importe quoi dans le tas qui appartient à cette instance de l’object. Mais avec les méthodes statiques, comme il n’y a pas de référence passée, cette méthode ne peut accéder à aucune variable ou méthode d’object car le contexte n’est pas connu.

    Si vous souhaitez que Java modifie la définition de sorte qu’un contexte d’object soit transmis pour chaque méthode, statique ou virtuelle, alors vous n’auriez essentiellement que des méthodes virtuelles.

    Comme quelqu’un l’a demandé dans un commentaire à l’op – quelle est votre raison et votre objective de vouloir cette fonctionnalité?

    Je ne connais pas beaucoup Ruby, comme cela a été mentionné par le PO, j’ai fait des recherches. Je vois que dans Ruby les classes sont vraiment un type d’object spécial et que l’on peut créer (même dynamicment) de nouvelles méthodes. Les classes sont des objects de classe complète dans Ruby, elles ne sont pas en Java. C’est quelque chose que vous devrez accepter lorsque vous travaillez avec Java (ou C #). Ce ne sont pas des langages dynamics, bien que C # ajoute des formes de dynamic. En réalité, Ruby n’a pas de méthodes “statiques” pour autant que je puisse trouver – dans ce cas, ce sont des méthodes sur l’object de classe singleton. Vous pouvez alors remplacer ce singleton par une nouvelle classe et les méthodes de l’object de la classe précédente appellent celles définies dans la nouvelle classe (correct?). Donc, si vous appelez une méthode dans le contexte de la classe d’origine, elle n’exécutera toujours que les statiques d’origine, mais l’appel d’une méthode dans la classe dérivée appelle des méthodes provenant du parent ou de la sous-classe. Intéressant et je peux voir une certaine valeur à cela. Cela prend un schéma de pensée différent.

    Puisque vous travaillez en Java, vous devrez vous adapter à cette façon de faire. Pourquoi ils ont fait ça? Eh bien, probablement pour améliorer les performances à la fois en fonction de la technologie et de la compréhension disponibles. Les langages informatiques évoluent constamment. Retournez assez loin et la POO n’existe pas. À l’avenir, il y aura d’autres idées nouvelles.

    EDIT : Un autre commentaire. Maintenant que je vois les différences et en tant que développeur Java / C #, je peux comprendre pourquoi les réponses des développeurs Java peuvent être déroutantes si vous venez d’un langage comme Ruby. Les méthodes static Java ne sont pas les mêmes que class méthodes de class Ruby. Les développeurs Java auront du mal à comprendre cela, tout comme ceux qui travaillent principalement avec un langage comme Ruby / Smalltalk. Je peux voir comment cela serait aussi déroutant par le fait que Java utilise également la “méthode de classe” comme un autre moyen de parler de méthodes statiques, mais ce même terme est utilisé différemment par Ruby. Java n’a pas de méthodes de classe de style Ruby (désolé); Ruby ne dispose pas de méthodes statiques de type Java qui ne sont que de vieilles fonctions de style procédural, comme dans C.

    Au fait, merci pour la question! J’ai appris quelque chose de nouveau aujourd’hui sur les méthodes de classe (style Ruby).

    Eh bien … la réponse est NON si vous pensez de la manière dont une méthode de remplacement devrait se comporter en Java. Mais vous n’obtenez aucune erreur de compilation si vous essayez de remplacer une méthode statique. Cela signifie que si vous essayez de passer outre, Java ne vous empêche pas de le faire. mais vous n’obtenez certainement pas le même effet que pour les méthodes non statiques. Remplacer dans Java signifie simplement que la méthode particulière serait appelée en fonction du type d’exécution de l’object et non du type de compilation de celui-ci (ce qui est le cas avec les méthodes statiques remplacées). Ok … des suppositions pour la raison pourquoi se comportent-elles étrangement? Parce qu’ils sont des méthodes de classe et que leur access est donc toujours résolu au moment de la compilation uniquement à l’aide des informations de type de compilation. Leur access à l’aide de références d’object est juste une liberté supplémentaire donnée par les concepteurs de Java et nous ne devrions certainement pas penser à arrêter cette pratique uniquement lorsqu’ils la restreignent 🙂

    Exemple : essayons de voir ce qui se passe si nous essayons de contourner une méthode statique: –

     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(Ssortingng[] args) { // ...... SuperClass superClassWithSuperCons = new SuperClass(); SuperClass superClassWithSubCons = new SubClass(); SubClass subClassWithSubCons = new SubClass(); superClassWithSuperCons.staticMethod(); superClassWithSubCons.staticMethod(); subClassWithSubCons.staticMethod(); // ... } } 

    Sortie : –
    SuperClass: inside staticMethod
    SuperClass: inside staticMethod
    SubClass: inside staticMethod

    Notez la deuxième ligne de la sortie. Si la méthode staticMethod avait été remplacée, cette ligne aurait dû être identique à la troisième ligne car nous invoquions le paramètre ‘staticMethod ()’ sur un object de type runtime comme ‘SubClass’ et non comme ‘SuperClass’. Cela confirme que les méthodes statiques sont toujours résolues en utilisant uniquement leurs informations de type heure de compilation.

    En général, il n’est pas logique d’autoriser la «substitution» des méthodes statiques, car il n’y aurait pas de moyen de déterminer lequel appeler à l’exécution. En prenant l’exemple Employé, si nous appelons RegularEmployee.getBonusMultiplier () – quelle méthode est censée être exécutée?

    Dans le cas de Java, on peut imaginer une définition de langage où il est possible de «remplacer» les méthodes statiques tant qu’elles sont appelées via une instance d’object. Cependant, tout ce que cela pourrait faire est de ré-implémenter des méthodes de classe régulières, en ajoutant la redondance au langage sans vraiment append de bénéfice.

    la substitution est réservée aux membres d’instance pour prendre en charge le comportement polymorphe. les membres de classe statiques n’appartiennent pas à une instance particulière. à la place, les membres statiques appartiennent à la classe et, par conséquent, la substitution n’est pas prise en charge car les sous-classes héritent uniquement des membres d’instance protégés et publics et non des membres statiques. 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 comstack-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 ressortingct 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. Ma faute.

    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 sortinges to override the static method, but will not encounter any compilation 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 compilation 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 comstack, Since the final keyword ressortingcts 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 – comstack 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 comstack 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 comstackr 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(Ssortingng[] 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"); // } } 

    Sortie:-

     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.

    Merci

    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(Ssortingng[] args) { OverridenStaticMeth osm = new OverrideStaticMeth(); osm.printValue(); System.out.println("now, from main"); printValue(); } }