Perché Java non consente l’override dei metodi statici?

Perché non è ansible sovrascrivere i metodi statici?

Se ansible, si prega di utilizzare un esempio.

    L’override dipende dall’avere un’istanza di una class. Il punto di polimorfismo è che è ansible sottoclass una class e gli oggetti che implementano quelle sottoclassi avranno comportamenti diversi per gli stessi metodi definiti nella superclass (e sovrascritti nelle sottoclassi). Un metodo statico non è associato a nessuna istanza di una class, quindi il concetto non è applicabile.

    Ci sono state due considerazioni che hanno guidato il design di Java che ha avuto un impatto su questo. Uno riguardava la performance: c’erano state molte critiche a Smalltalk sul fatto che fosse troppo lento (la raccolta dei rifiuti e le chiamate polimorfiche facevano parte di questo) e i creatori di Java erano determinati a evitarlo. Un altro era la decisione che il pubblico di destinazione per Java era sviluppatori C ++. Fare in modo che i metodi statici funzionino nel modo in cui hanno avuto il vantaggio della familiarità per i programmatori C ++ ed è stato anche molto veloce, perché non è necessario attendere il runtime per capire quale metodo chiamare.

    Personalmente penso che questo sia un difetto nella progettazione di Java. Sì, sì, capisco che i metodi non statici sono collegati a un’istanza mentre i metodi statici sono collegati a una class, ecc. Ecc. Tuttavia, considera il seguente codice:

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

    Questo codice non funzionerà come potresti immaginare. Vale a dire, SpecialEmployee ottiene un bonus del 2% proprio come i dipendenti regolari. Ma se rimuovi le “statiche”, allora SpecialEmployee ottiene un bonus del 3%.

    (Certamente, questo esempio è uno stile di programmazione povero in quanto nella realtà è probabile che il moltiplicatore di bonus si trovi in ​​un database da qualche parte piuttosto che codificato, ma è solo perché non volevo impantanare l’esempio con molto di codice irrilevante al punto.)

    Mi sembra abbastanza plausibile che tu voglia rendere statico getBonusMultiplier. Forse vuoi essere in grado di visualizzare il moltiplicatore di bonus per tutte le categorie di dipendenti, senza la necessità di avere un’istanza di un dipendente in ogni categoria. Quale sarebbe il punto di cercare tali esempi di istanze? Cosa succede se stiamo creando una nuova categoria di dipendenti e non abbiamo ancora assegnato dipendenti? Questa è abbastanza logicamente una funzione statica.

    Ma non funziona.

    E sì, sì, posso pensare a un numero qualsiasi di modi per riscrivere il codice sopra per farlo funzionare. Il mio punto non è che crea un problema irrisolvibile, ma crea una trappola per il programmatore incauto, perché la lingua non si comporta come penso che una persona ragionevole si aspetterebbe.

    Forse se provassi a scrivere un compilatore per un linguaggio OOP, vedrei rapidamente perché implementarlo in modo che le funzioni statiche possano essere superate sarebbe difficile o imansible.

    O forse c’è una buona ragione per cui Java si comporta in questo modo. Qualcuno può indicare un vantaggio per questo comportamento, qualche categoria di problemi che è resa più facile da questo? Voglio dire, non limitarmi alle specifiche del linguaggio Java e dire “guarda, questo è documentato come si comporta”. Lo so. Ma c’è una buona ragione perché DOVREBBE comportarsi in questo modo? (Oltre l’ovvio “far funzionare bene era troppo difficile” …)

    Aggiornare

    @VicKirk: Se intendi che si tratta di “ctriggers progettazione” perché non si adatta a come Java gestisce la statica, la mia risposta è “Beh, duh, ovviamente”. Come ho detto nel mio post originale, non funziona. Ma se vuoi dire che è un cattivo design nel senso che ci sarebbe qualcosa di fondamentalmente sbagliato in un linguaggio in cui questo ha funzionato, vale a dire dove la statica potrebbe essere scavalcata proprio come le funzioni virtuali, che ciò introdurrebbe in qualche modo un’ambiguità o sarebbe imansible implementare in modo efficiente o alcuni di questi, rispondo, “Perché? Cosa c’è di sbagliato con il concetto?”

    Penso che l’esempio che do sia una cosa molto naturale da voler fare. Ho una class che ha una funzione che non dipende da nessun dato di istanza e che potrei ragionevolmente desiderare di chiamare indipendente da un’istanza, oltre a voler chiamare da un metodo di istanza. Perché questo non dovrebbe funzionare? Ho incontrato questa situazione un discreto numero di volte nel corso degli anni. In pratica, mi aggirano rendendo la funzione virtuale e quindi creando un metodo statico il cui unico scopo nella vita è essere un metodo statico che trasmette la chiamata al metodo virtuale con un’istanza fittizia. Sembra un modo molto approssimativo per arrivarci.

    La risposta breve è: è del tutto ansible, ma Java non lo fa.

    Ecco un codice che illustra lo stato attuale delle cose in Java:

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

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

    Se lo esegui (l’ho fatto su un Mac, da Eclipse, usando Java 1.6) ottieni:

     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. 

    Qui, gli unici casi che potrebbero essere una sorpresa (e di cui tratta la domanda) sembrano essere il primo caso:

    “Il tipo run-time non viene utilizzato per determinare quali metodi statici vengono chiamati, anche se chiamati con un’istanza dell’object ( obj.staticMethod() ).”

    e l’ ultimo caso:

    “Quando si chiama un metodo statico all’interno di un metodo object di una class, il metodo statico scelto è quello accessibile dalla class stessa e non dalla class che definisce il tipo di runtime dell’object.”

    Chiamare con un’istanza di object

    La chiamata statica viene risolta in fase di compilazione, mentre una chiamata al metodo non statico viene risolta in fase di esecuzione. Si noti che anche se i metodi statici sono ereditati (dal genitore) non vengono sovrascritti (dal bambino). Questa potrebbe essere una sorpresa se ti aspettavi il contrario.

    Chiamata dall’interno di un metodo object

    Le chiamate al metodo dell’object vengono risolte utilizzando il tipo di runtime, ma le chiamate al metodo statiche (di class ) vengono risolte utilizzando il tipo compile-time (dichiarato).

    Cambiare le regole

    Per modificare queste regole, in modo che l’ultima chiamata nell’esempio denominata Child.printValue() , le chiamate statiche dovrebbero essere fornite con un tipo in fase di esecuzione, anziché il compilatore che risolve la chiamata in fase di compilazione con la class dichiarata dell’object (o contesto). Le chiamate statiche potrebbero quindi utilizzare la gerarchia di tipi (dinamici) per risolvere la chiamata, proprio come fanno oggi le chiamate al metodo degli oggetti.

    Questo sarebbe facilmente fattibile (se abbiamo cambiato Java: -O), e non è affatto irragionevole, tuttavia, ha alcune considerazioni interessanti.

    La considerazione principale è che dobbiamo decidere quali chiamate al metodo statico dovrebbero fare questo.

    Al momento, Java ha questa “stranezza” nella lingua in cui le chiamate obj.staticMethod() vengono sostituite dalle chiamate ObjectClass.staticMethod() (normalmente con un avviso). [ Nota: ObjectClass è il tipo di object in fase di compilazione] Questi sarebbero buoni candidati per ignorare in questo modo, prendendo il tipo di obj run-time.

    Se lo facessimo, renderemmo i corpi del metodo più difficili da leggere: le chiamate statiche in una class genitore potrebbero potenzialmente essere “reinstradate” dynamicmente . Per evitare ciò dovremmo chiamare il metodo statico con un nome di class – e questo rende le chiamate più ovviemente risolte con la gerarchia dei tipi in fase di compilazione (come ora).

    Gli altri modi di invocare un metodo statico sono più complicati: this.staticMethod() dovrebbe significare lo stesso di obj.staticMethod() , prendendo il tipo run-time di this . Tuttavia, questo potrebbe causare dei grattacapi con programmi esistenti, che chiamano metodi statici apparentemente locali senza decorazione (che è probabilmente equivalente a this.method() ).

    Che dire delle chiamate non staticMethod() ? Suggerisco di fare lo stesso come oggi, e usare il contesto di class locale per decidere cosa fare. Altrimenti ne deriverebbe una grande confusione. Ovviamente significa che method() significherebbe this.method() se method era un method non statico e ThisClass.method() se method era un metodo statico. Questa è un’altra fonte di confusione.

    Altre considerazioni

    Se cambiassimo questo comportamento (e rendessimo le chiamate statiche potenzialmente dynamicmente non locali), vorremmo probabilmente rivedere il significato di final , private e protected come qualificatori sui metodi static di una class. Dovremmo quindi abituarci al fatto che public final metodi private static e public final non sono sovrascritti e possono quindi essere risolti in modo sicuro in fase di compilazione e sono “sicuri” da leggere come riferimenti locali.

    In realtà ci siamo sbagliati.
    Nonostante Java non consenta di sovrascrivere i metodi statici per impostazione predefinita, se si osserva attentamente la documentazione delle classi Class e Method in Java, è ancora ansible trovare un modo per emulare metodi statici che eseguono l’override seguendo la soluzione alternativa:

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

    Risultato risultante:

     0.02 0.02 0.02 0.03 

    cosa stavamo cercando di ottenere 🙂

    Anche se dichiariamo la terza variabile Carl come RegularEmployee e assegniamo ad essa l’istanza di SpecialEmployee, avremo ancora la chiamata del metodo RegularEmployee nel primo caso e la chiamata del metodo SpecialEmployee nel secondo caso

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

    basta guardare la console di output:

     0.02 0.03 

    😉

    I metodi statici sono trattati come globali dalla JVM, non sono affatto associati a un’istanza dell’object.

    Potrebbe essere concettualmente ansible se poteste chiamare metodi statici da oggetti di class (come in linguaggi come Smalltalk) ma non è il caso in Java.

    MODIFICARE

    Puoi sovraccaricare il metodo statico, va bene. Ma non è ansible sovrascrivere un metodo statico, perché la class non è un object di prima class. È ansible utilizzare reflection per ottenere la class di un object in fase di esecuzione, ma l’object che si ottiene non è parallelo alla gerarchia di classi.

     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 

    Puoi riflettere sulle classi, ma si ferma qui. Non si invoca un metodo statico utilizzando clazz1.staticMethod() , ma utilizzando MyClass.staticMethod() . Un metodo statico non è legato ad un object e quindi non esiste una nozione di thissuper in un metodo statico. Un metodo statico è una funzione globale; di conseguenza non c’è nemmeno la nozione di polimorfismo e, quindi, il metodo che ha la precedenza non ha senso.

    Ma questo potrebbe essere ansible se MyClass fosse un object in fase di esecuzione su cui invochi un metodo, come in Smalltalk (o forse JRuby come suggerisce un commento, ma non so nulla di JRuby).

    Ah già, un’altra cosa. È ansible richiamare un metodo statico attraverso un object obj1.staticMethod() ma quello zucchero sintattico veramente per MyClass.staticMethod() e dovrebbe essere evitato. Solleva di solito un avvertimento nel moderno IDE. Non so perché abbiano mai permesso questa scorciatoia.

    L’override del metodo è reso ansible dall’invio dinamico , il che significa che il tipo dichiarato di un object non determina il suo comportamento, ma piuttosto il suo tipo di runtime:

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

    Anche se sia lassie che kermit sono dichiarati come oggetti di tipo Animal , il loro comportamento (metodo .speak() ) varia perché l’invio dinamico vincolerà solo il metodo .speak() a un’implementazione in fase di esecuzione – non al momento della compilazione.

    Ora, ecco dove la parola chiave static inizia ad avere un senso: la parola “statico” è un antonimo per “dinamico”. Quindi il motivo per cui non è ansible sovrascrivere i metodi statici è perché non ci sono dispatch dinamici sui membri statici – perché static significa letteralmente “non dinamico”. Se spedivano dynamicmente (e quindi potevano essere cancellati) la parola chiave static non avrebbe più senso.

    Sì. Praticamente Java consente l’override del metodo statico e No teoricamente, se si esegue l’Override di un metodo statico in Java, esso verrà compilato ed eseguito senza problemi, ma perderà il polimorfismo, che è la proprietà base di Java. Leggerai Ovunque che non è ansible provare te stesso compilando e correndo. otterrai la tua risposta Ad esempio, se si dispone di un animale di class e di un metodo statico eat () e si ignora il metodo statico nella sottoclass, viene chiamato Cane. Poi, ovunque tu abbia assegnato un object Cane a un animale e chiami mangiare () secondo Java, il cane mangia () avrebbe dovuto essere chiamato, ma negli statici animali sovradimensionati, il cibo () sarà chiamato.

     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 

    Secondo Polymorphism Principle of Java, l’output dovrebbe essere Dog Eating .
    Ma il risultato è stato diverso perché per supportare il polimorfismo Java utilizza Late Binding che indica che i metodi vengono chiamati solo in fase di esecuzione ma non nel caso di metodi statici. Nei metodi statici, il compilatore chiama i metodi al momento della compilazione piuttosto che al tempo di esecuzione, quindi otteniamo i metodi in base al riferimento e non in base all’object un riferimento a contenente ecco perché è ansible dire Praticamente supporta l’overder statico ma teoricamente non funziona ‘t.

    In Java (e in molti linguaggi OOP, ma non posso parlare per tutti, e alcuni non hanno affatto statico) tutti i metodi hanno una firma fissa – i parametri e i tipi. In un metodo virtuale, il primo parametro è implicito: un riferimento all’object stesso e quando chiamato dall’interno dell’object, il compilatore lo aggiunge automaticamente.

    Non c’è differenza per i metodi statici: hanno ancora una firma fissa. Tuttavia, dichiarando il metodo statico hai esplicitamente dichiarato che il compilatore non deve includere il parametro object implicito all’inizio di tale firma. Pertanto, qualsiasi altro codice che chiami questo deve non tentare di mettere un riferimento a un object nello stack . Se lo facesse, l’esecuzione del metodo non funzionerebbe poiché i parametri sarebbero nel posto sbagliato – spostato di uno – nello stack.

    A causa di questa differenza tra i due; i metodi virtuali hanno sempre un riferimento all’object contesto (cioè this ), quindi è ansible fare riferimento a qualsiasi cosa all’interno dell’heap appartenente a quell’istanza dell’object. Ma con i metodi statici, dato che non c’è alcun riferimento passato, quel metodo non può accedere a nessun object variabile e metodo poiché il contesto non è noto.

    Se si desidera che Java cambi la definizione in modo che venga passato un contesto object per ogni metodo, statico o virtuale, in pratica si avranno solo metodi virtuali.

    Come qualcuno ha chiesto in un commento all’opzione – qual è la tua ragione e il tuo scopo per volere questa funzione?

    Non conosco molto Ruby, poiché questo è stato menzionato dall’OP, ho fatto delle ricerche. Vedo che nelle classi Ruby sono davvero un tipo speciale di object e si possono creare (anche dynamicmente) nuovi metodi. Le classi sono oggetti di class completa in Ruby, non sono in Java. Questo è solo qualcosa che dovrai accettare quando lavori con Java (o C #). Questi non sono linguaggi dinamici, anche se C # sta aggiungendo alcune forms di dynamic. In realtà, Ruby non ha metodi “statici” per quanto ho potuto trovare – in questo caso questi sono metodi sull’object class singleton. È quindi ansible sovrascrivere questo singleton con una nuova class e i metodi nell’object class precedente chiameranno quelli definiti nella nuova class (corretto?). Quindi, se hai chiamato un metodo nel contesto della class originale, eseguirà comunque solo la statica originale, ma chiamando un metodo nella class derivata, chiamerebbe i metodi dal genitore o dalla sottoclass. Interessante e posso vedere un certo valore in questo. Ci vuole un modello di pensiero diverso.

    Dato che lavori in Java, dovrai adattarti a questo modo di fare le cose. Perché hanno fatto questo? Bene, probabilmente per migliorare le prestazioni al momento in base alla tecnologia e alla comprensione che era disponibile. Le lingue informatiche sono in continua evoluzione. Torna abbastanza lontano e non esiste nulla come OOP. In futuro, ci saranno altre nuove idee.

    EDIT : un altro commento. Ora che vedo le differenze e io stesso sviluppatore Java / C #, posso capire perché le risposte che ottieni dagli sviluppatori Java possono essere fonte di confusione se provieni da una lingua come Ruby. I metodi static Java non sono uguali ai metodi della class Ruby. Gli sviluppatori Java avranno difficoltà a capirlo, così come al contrario quelli che lavorano principalmente con un linguaggio come Ruby / Smalltalk. Posso vedere come questo sarebbe anche molto confuso dal fatto che Java usi anche “metodo di class” come un altro modo per parlare di metodi statici, ma questo stesso termine è usato in modo diverso da Ruby. Java non ha metodi di class in stile Ruby (mi dispiace); Ruby non ha metodi statici in stile Java che sono in realtà solo vecchie funzioni di stile procedurale, come trovate in C.

    A proposito – grazie per la domanda! Ho imparato qualcosa di nuovo per me oggi sui metodi di class (stile Ruby).

    Bene … la risposta è NO se pensi dalla prospettiva di come un metodo sovrascritto dovrebbe comportarsi in Java. Ma non si ottiene alcun errore del compilatore se si tenta di sovrascrivere un metodo statico. Ciò significa che se provi a scavalcare, Java non ti impedisce di farlo; ma certamente non ottieni lo stesso effetto dei metodi non statici. L’override in Java significa semplicemente che il particolare metodo sarebbe chiamato in base al tipo di tempo di esecuzione dell’object e non al tipo di tempo di compilazione di esso (che è il caso dei metodi statici sovrascritti). Va bene … qualche ipotesi per il motivo per cui si comportano in modo strano? Perché sono metodi di class e quindi l’accesso ad essi viene sempre risolto durante la compilazione usando solo le informazioni sul tipo di tempo di compilazione. Accedervi usando riferimenti agli oggetti è solo una libertà in più data dai designer di Java e non dovremmo certo pensare di fermare quella pratica solo quando la limitano 🙂

    Esempio : proviamo a vedere cosa succede se proviamo a scavalcare un metodo statico: –

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

    Risultato : –
    SuperClass: inside staticMethod
    SuperClass: inside staticMethod
    SubClass: inside staticMethod

    Notare la seconda riga dell’output. Se il parametro staticMethod fosse stato cancellato, questa riga avrebbe dovuto essere identica alla terza riga poiché stiamo invocando ‘staticMethod ()’ su un object di Runtime Type come ‘SubClass’ e non come ‘SuperClass’. Ciò conferma che i metodi statici vengono sempre risolti usando solo le informazioni sul tipo di tempo compilato.

    In generale, non ha senso consentire l’override dei metodi statici in quanto non ci sarebbe un buon modo per determinare quale chiamare in fase di esecuzione. Prendendo l’esempio Employee, se chiamiamo RegularEmployee.getBonusMultiplier () – quale metodo dovrebbe essere eseguito?

    Nel caso di Java, si potrebbe immaginare una definizione del linguaggio in cui è ansible “sovrascrivere” i metodi statici fintanto che vengono chiamati attraverso un’istanza dell’object. Tuttavia, tutto ciò che farebbe è di ri-implementare i normali metodi di class, aggiungendo ridondanza alla lingua senza aggiungere alcun beneficio.

    overriding is reserved for instance members to support polymorphic behaviour. static class members do not belong to a particular instance. instead, static members belong to the class and as a result overriding is not supported because subclasss only inherit protected and public instance members and not static members. 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. Colpa mia.

    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 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 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 classs 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.

    Grazie

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