Why doesn't Java allow overriding of static methods?

287,741

Solution 1

Overriding depends on having an instance of a class. The point of polymorphism is that you can subclass a class and the objects implementing those subclasses will have different behaviors for the same methods defined in the superclass (and overridden in the subclasses). A static method is not associated with any instance of a class so the concept is not applicable.

There were two considerations driving Java's design that impacted this. One was a concern with performance: there had been a lot of criticism of Smalltalk about it being too slow (garbage collection and polymorphic calls being part of that) and Java's creators were determined to avoid that. Another was the decision that the target audience for Java was C++ developers. Making static methods work the way they do had the benefit of familiarity for C++ programmers and was also very fast, because there's no need to wait until runtime to figure out which method to call.

Solution 2

Personally I think this is a flaw in the design of Java. Yes, yes, I understand that non-static methods are attached to an instance while static methods are attached to a class, etc etc. Still, consider the following code:

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

This code will not work as you might expect. Namely, SpecialEmployee's get a 2% bonus just like regular employees. But if you remove the "static"s, then SpecialEmployee's get a 3% bonus.

(Admittedly, this example is poor coding style in that in real life you would likely want the bonus multiplier to be in a database somewhere rather than hard-coded. But that's just because I didn't want to bog down the example with a lot of code irrelevant to the point.)

It seems quite plausible to me that you might want to make getBonusMultiplier static. Perhaps you want to be able to display the bonus multiplier for all the categories of employees, without needing to have an instance of an employee in each category. What would be the point of searching for such example instances? What if we are creating a new category of employee and don't have any employees assigned to it yet? This is quite logically a static function.

But it doesn't work.

And yes, yes, I can think of any number of ways to rewrite the above code to make it work. My point is not that it creates an unsolvable problem, but that it creates a trap for the unwary programmer, because the language does not behave as I think a reasonable person would expect.

Perhaps if I tried to write a compiler for an OOP language, I would quickly see why implementing it so that static functions can be overriden would be difficult or impossible.

Or perhaps there is some good reason why Java behaves this way. Can anyone point out an advantage to this behavior, some category of problem that is made easier by this? I mean, don't just point me to the Java language spec and say "see, this is documented how it behaves". I know that. But is there a good reason why it SHOULD behave this way? (Besides the obvious "making it work right was too hard"...)

Update

@VicKirk: If you mean that this is "bad design" because it doesn't fit how Java handles statics, my reply is, "Well, duh, of course." As I said in my original post, it doesn't work. But if you mean that it is bad design in the sense that there would be something fundamentally wrong with a language where this worked, i.e. where statics could be overridden just like virtual functions, that this would somehow introduce an ambiguity or it would be impossible to implement efficiently or some such, I reply, "Why? What's wrong with the concept?"

I think the example I give is a very natural thing to want to do. I have a class that has a function that does not depend on any instance data, and which I might very reasonably want to call independent of an instance, as well as wanting to call from within an instance method. Why should this not work? I've run into this situation a fair number of times over the years. In practice I get around it by making the function virtual, and then creating a static method whose only purpose in life is to be a static method that passes the call on to the virtual method with a dummy instance. That seems like a very roundabout way to get there.

Solution 3

The short answer is: it is entirely possible, but Java doesn't do it.

Here is some code which illustrates the current state of affairs 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();
  }
}

If you run this (I did it on a Mac, from Eclipse, using Java 1.6) you get:

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.

Here, the only cases which might be a surprise (and which the question is about) appear to be the first case:

"The run-time type is not used to determine which static methods are called, even when called with an object instance (obj.staticMethod())."

and the last case:

"When calling a static method from within an object method of a class, the static method chosen is the one accessible from the class itself and not from the class defining the run-time type of the object."

Calling with an object instance

The static call is resolved at compile-time, whereas a non-static method call is resolved at run-time. Notice that although static methods are inherited (from parent) they are not overridden (by child). This could be a surprise if you expected otherwise.

Calling from within an object method

Object method calls are resolved using the run-time type, but static (class) method calls are resolved using the compile-time (declared) type.

Changing the rules

To change these rules, so that the last call in the example called Child.printValue(), static calls would have to be provided with a type at run-time, rather than the compiler resolving the call at compile-time with the declared class of the object (or context). Static calls could then use the (dynamic) type hierarchy to resolve the call, just as object method calls do today.

This would easily be doable (if we changed Java :-O), and is not at all unreasonable, however, it has some interesting considerations.

The main consideration is that we need to decide which static method calls should do this.

At the moment, Java has this "quirk" in the language whereby obj.staticMethod() calls are replaced by ObjectClass.staticMethod() calls (normally with a warning). [Note: ObjectClass is the compile-time type of obj.] These would be good candidates for overriding in this way, taking the run-time type of obj.

If we did it would make method bodies harder to read: static calls in a parent class could potentially be dynamically "re-routed". To avoid this we would have to call the static method with a class name -- and this makes the calls more obviously resolved with the compile-time type hierarchy (as now).

The other ways of invoking a static method are more tricky: this.staticMethod() should mean the same as obj.staticMethod(), taking the run-time type of this. However, this might cause some headaches with existing programs, which call (apparently local) static methods without decoration (which is arguably equivalent to this.method()).

So what about unadorned calls staticMethod()? I suggest they do the same as today, and use the local class context to decide what to do. Otherwise great confusion would ensue. Of course it means that method() would mean this.method() if method was a non-static method, and ThisClass.method() if method were a static method. This is another source of confusion.

Other considerations

If we changed this behaviour (and made static calls potentially dynamically non-local), we would probably want to revisit the meaning of final, private and protected as qualifiers on static methods of a class. We would then all have to get used to the fact that private static and public final methods are not overridden, and can therefore be safely resolved at compile-time, and are "safe" to read as local references.

Solution 4

Actually we were wrong.
Despite Java doesn't allow you to override static methods by default, if you look thoroughly through documentation of Class and Method classes in Java, you can still find a way to emulate static methods overriding by following workaround:

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

Resulting output:

0.02
0.02
0.02
0.03

what we were trying to achieve :)

Even if we declare third variable Carl as RegularEmployee and assign to it instance of SpecialEmployee, we will still have call of RegularEmployee method in first case and call of SpecialEmployee method in second case

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

just look at output console:

0.02
0.03

;)

Solution 5

Static methods are treated as global by the JVM, there are not bound to an object instance at all.

It could conceptually be possible if you could call static methods from class objects (like in languages like Smalltalk) but it's not the case in Java.

EDIT

You can overload static method, that's ok. But you can not override a static method, because class are no first-class object. You can use reflection to get the class of an object at run-time, but the object that you get does not parallel the class hierarchy.

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

You can reflect over the classes, but it stops there. You don't invoke a static method by using clazz1.staticMethod(), but using MyClass.staticMethod(). A static method is not bound to an object and there is hence no notion of this nor super in a static method. A static method is a global function; as a consequence there is also no notion of polymorphism and, therefore, method overriding makes no sense.

But this could be possible if MyClass was an object at run-time on which you invoke a method, as in Smalltalk (or maybe JRuby as one comment suggest, but I know nothing of JRuby).

Oh yeah... one more thing. You can invoke a static method through an object obj1.staticMethod() but that really syntactic sugar for MyClass.staticMethod() and should be avoided. It usually raises a warning in modern IDE. I don't know why they ever allowed this shortcut.

Share:
287,741
Saurabh Gokhale
Author by

Saurabh Gokhale

Updated on July 08, 2022

Comments

  • Saurabh Gokhale
    Saurabh Gokhale almost 2 years

    Why is it not possible to override static methods?

    If possible, please use an example.

  • Chandra Sekar
    Chandra Sekar over 14 years
    Even many modern languages like Ruby have class-methods and allow overriding them.
  • Jay
    Jay over 14 years
    Classes do exist as objects in Java. See the "Class" class. I can say myObject.getClass() and it will return me an instance of the appropriate class object.
  • Powerlord
    Powerlord over 14 years
    "You cannot call static methods through an instance" Actually, one of Java's quirks is that you CAN call static methods through an instance, even though it's an exceedingly bad idea.
  • Powerlord
    Powerlord over 14 years
    Although this code works in Java, it's a quirk of Java, which lets you call static methods on an instance. It would fail in C#, because C# doesn't allow you to call static methods as an instance method like you're doing on the salary.multiply line.
  • vickirk
    vickirk over 14 years
    This example is just a bad design and does not highlight any 'flaw' with the implementation of static methods. I can't think of any example where I would want to override them, would you really want to write code like bonus = (obj instanceof B) ? B.bonus() : A.bonus(). What if it was overridden on type C, or a third party adds type D, every bit of code that uses the methods is then broken. True you could write the above with an instance variable but then it would be an instance method, as it then requires an instance to resolve the method!
  • vickirk
    vickirk over 14 years
    BTW, as things are instance.staticMethod() is likely to be optimised with IntanceClass.staticMethod()
  • ewernli
    ewernli over 14 years
    Class are not first-class entity in java. You can call a static method with obj.staticMethod() or staticMethod() but the compiler treats that as MyClass.staticMethod() depending on the scope it is compiled. You should always use MyClass.staticMethod() to avoid the confusion that you just described. See my answer which I refined.
  • Jay
    Jay over 14 years
    @Bemrose: But that's my point: Why shouldn't I be allowed to do that? Maybe my intuitive concept of what a "static" should do is different from yours, but basically I think of a static as a method that CAN be static because it doesn't use any instance data, and which SHOULD be static because you may want to call it independently of an instance. A static is clearly tied to a class: I expect Integer.valueOf to be tied to Integers and Double.valueOf to be tied to Doubles.
  • Powerlord
    Powerlord over 14 years
    @Jay: Honestly, you shouldn't. I don't know why the developers of Java decided to do it that way. It's basically a compiler trick, as vickirk implied.
  • Jay
    Jay over 14 years
    @ewernli & Bemrose: Yes yes, that's how it IS. I'm not debating that. As the code in my example doesn't work, of course I wouldn't try to write it. My question is why it is that way. (I fear this is turning into one of those conversations where we're just not communicating. "Excuse me Mr Salesman, can I get one of these in red?" "No, it costs $5." "Yes, I know it costs $5, but can I get a red one?" "Sir, I just told you that it costs $5." "Okay, I know the price, but I was asking about the color." "I already told you the price!" etc.)
  • Jay
    Jay over 14 years
    Intuitively, I would think it should work just like a virtual function. If B extends A and both A and B have virtual functions named doStuff, the compiler knows that instances of A should use A.doStuff and instances of B should use B.doStuff. Why can't it do the same with static functions? After all, the compiler knows what class each object is an instance of.
  • meriton
    meriton over 14 years
    Erm ... Jay, a static method need not be (generally is not) called on an instance ...
  • Yishai
    Yishai over 14 years
    Jay, regarding your last comment, it would make much more sense to have the instance method call the static method and have the implementation in the static method. Why create an instance when you don't need one?
  • Yishai
    Yishai over 14 years
    I think that ultimately this code is confusing. Consider if the instance is passed as a parameter. Then you are saying that the runtime instance should dictate which static method is called. That basically makes a whole separate hierarchy parallel to the existing instance one. Now what if a subclass defines the same method signature as non-static? I think that the rules would make things quite complicated. It is precisely these kinds of language complications that Java tries to avoid.
  • CPerkins
    CPerkins over 14 years
    @meriton, but then it's even easier, no? If a static method is called using a classname, you'd use the method appropriate for the class.
  • Jay
    Jay over 14 years
    @Yishai: RE "Runtime instance dictate which static method is called": Exactly. I don't see why you can't do anything with a static that you can do with a virtual. "Separate hierarchy": I'd say, Make it part of the same hierarchy. Why aren't statics included in the same hierarchy? "Subsclass defines the same signature non-static": I presume that would be illegal, just like it's illegal to, say, have a subclass override a function with an identical signature but a different return type, or to not throw all the exceptions that the parent throws, or to have a narrower scope.
  • Jay
    Jay over 14 years
    I put the real logic in a virtual and create a static to call it with a dummy object, rather than putting the real logic in a virtual, because the whole point is that I need to override the logic in a subclass, and Java doesn't allow me to override a static.
  • PSpeed
    PSpeed over 14 years
    But then what is overriding doing for you. If you call A.doStuff() should it use the version that was overridden in "B extends A" or the version that was overridden in "C extends A". And if you have C or B then you are calling those versions anyway... no overriding necessary.
  • vickirk
    vickirk over 14 years
    "I think the example I give is a very natural thing to want to do. I have a class that has a function that does not depend on any instance data" - but it depends on what type the instance of an object is. How could you possibly call the correct method if you don't know what type of object it is, polymorphism is not driven by object state, rather than the behavior an instance exhibits.
  • Jay
    Jay over 14 years
    If I want to call a static function without having an instance, then yes, of course I have to specify the class. It seems very natural to me that I should be able to call a static function via a class name and either a static or virtual function via an object instance. Why not?
  • Jay
    Jay over 14 years
    PS I don't want to circle around an argument forever. If we disagree, at some point we have to just say, "Okay, we disagree and neither is about to convince the other." But if you two want to continue to trade comments, I'm game.
  • vickirk
    vickirk over 14 years
    But surely if you need an instance of an object to resolve which static method to call it is just not a static method. "Okay, we disagree and neither is about to convince the other." - I'm going to leave it at that :-)
  • ewernli
    ewernli over 14 years
    You get only a "description" of the class -- not the class itself. But the difference is subtle.
  • Lawrence Dol
    Lawrence Dol about 14 years
    I think Jay has a point - it surprised me too when I discovered that statics could not be overridden. In part because if I have A with method someStatic() and B extends A, then B.someMethod() binds to the method in A. If I subsequently add someStatic() to B, the calling code still invokes A.someStatic() until I recompile the calling code. Also it surprised me that bInstance.someStatic() uses the declared type of bInstance, not the runtime type because it binds at compile not link, so A bInstance; ... bInstance.someStatic() invokes A.someStatic() if if B.someStatic() exists.
  • Lawrence Dol
    Lawrence Dol about 14 years
    But ultimately, I find myself agreeing with vickirk: "surely if you need an instance of an object to resolve which static method to call it is just not a static method". I wish Java had never allowed static invocation via an instance reference, and I wish that they would now add a compiler lint switch to issue a warning for it.
  • Jay
    Jay about 14 years
    @meriton: It is true that a static method is generally not called with an instance, but I presume that is because such a call does nothing useful given the current design of Java! I am suggesting that an alternative design might have been a better idea. BTW, in a very real sense static functions are called with an instance quite routinely: When you call the static function from within a virtual function. Then you implicitly get this.function(), i.e. the current instance.
  • Kevin Brock
    Kevin Brock about 14 years
    @Jay: No, that is not true. The compiler will generate a different type of call. For all virtual method calls, the compiler puts a reference to this on the stack. With a static method call (even, unfortunately with Java's this.staticMethod()) there is no hidden reference so the compiler really strips off this. from that call.
  • Jay
    Jay about 14 years
    @Kevin: Okay, my statement was poorly worded. I meant that if you call a static function from within the same class, you get the same function that you would get if you wrote "this.function()", i.e. the static in the "current" class, or the first one found as you chase up the hierarchy. (I think that's true: I'll have to check that out.) I did not mean to imply that it turned the call into a virtual call.
  • Jay
    Jay about 14 years
    @SoftwareMonkey: I don't think it's inherently unreasonable to say that you CAN USE an instance to decide which static method to call. Yes, if you MUST HAVE an instance, then it's not a static any more. But to say that the compiler could examine the instance, see what class it is, and then use that to decide which static function ... seems quite reasonable to me. Again, see my example that started this argument ... I mean thread.
  • Lawrence Dol
    Lawrence Dol about 14 years
    @Jay: That's the problem - the compiler can't examine the "instance" to see what it is, since the instance doesn't exist until runtime. The compiler can only invoke the static method based on the declared type, which could be the actual type or any of its super classes.
  • Jay
    Jay about 14 years
    @SoftwareMonkey: We're back to "is" versus "should be". Yes, what you are saying is how Java is. I'm not disputing that. But I see no reason why it couldn't choose a static method based on the runtime type, just as it chooses a virtual method based on the runtime type. Why couldn't static methods be included in the pointer table along with the virtual methods? Yes, this would mean there would be two ways to get to them. But so what?
  • mathk
    mathk almost 14 years
    You still have class but it is hidden in the VM (near the class loader), user have almost no access to it.
  • jmucchiello
    jmucchiello almost 14 years
    Of course, there's no reason why Java couldn't pass a "Class" object as a hidden parameter to static methods. It just wasn't designed to do it.
  • Admin
    Admin over 12 years
    ...but only "correct" in Java. For instance, Scala's equivalent of "static classes" (which are called objects) allow overloading of methods.
  • Richard
    Richard over 12 years
    Objective-C also allows overriding class methods.
  • Richard JP Le Guen
    Richard JP Le Guen over 11 years
    Indeed Java does allow static members to be accessed via instances: see Static variable in Java
  • Steve Powell
    Steve Powell over 11 years
    There is a compile-time type hierarchy and a run-time type hierarchy. It makes perfect sense to ask why a static method call doesn't avail itself of the run-time type hierarchy in those circumstances where there is one. In Java this happens when calling a static method from an object (obj.staticMethod()) -- which is allowed and uses the compile-time types. When the static call is in a non-static method of a class, the "current" object could be a derived type of the class -- but static methods defined on the derived types are not considered (they are in the run-time type hierarchy).
  • Steve Powell
    Steve Powell over 11 years
    I should have made it clear: it is not true that the concept is not applicable.
  • Steve Powell
    Steve Powell over 11 years
    @Jay I would propose that obj.staticMethod() uses the run-time type hierarchy but that plain staticMethod() (in a class method) uses the compile-time type hierarchy. This means that your example would not work, unless you changed it to this.staticMethod(). Notice that this has the run-time type that you want to use.
  • Steve Powell
    Steve Powell over 11 years
    I think this answer doesn't answer the question -- which was "Why not?" The reasons why are obscure, and it is not at all the case that the concept wouldn't work in Java.
  • Nathan Hughes
    Nathan Hughes over 11 years
    @Steve: by "the concept is not applicable" i meant, it's not helpful to try to think about static methods in terms of OO or class methods. as to why, it's one of those performance hacks, like having primitive types, where Java's creators were trying to avoid a rep for being slow like Smalltalk had at the time. would it help to modify the answer along those lines?
  • Gimby
    Gimby over 11 years
    A proper modern IDE will generate a warning when you do that though, so at least you can catch it while Oracle can keep the backwards compatibility thing going.
  • EricS
    EricS about 11 years
    What's flawed in your example is your motivation for wanting to make getBonusMultiplier() static. The thing that it makes sense to have static and not per-instance copies of proliferating is the multiplier itself. What makes more sense is for each class to have constants for this, as in static final BigDecimal multiplier = new BigDecimal(".03"); Then a non-static getBonusMultiplier() method in each class can use the static multiplier from that class.
  • Jay
    Jay about 11 years
    Well, okay, I was trying to create a simple example, and yes, in this case you could solve the problem by creating a variable to hold the multiplier. But surely it's not hard to imagine real-world cases that are not that simple. Like, for salesman the bonus is based on their sales for the quarter, for managers it's based on revenue for their division, and for clerical people it's a percentage of their salary. The point is whether there is a way to accomplish this particular example, but whether there is a way to accomplish the idea in general, in more complex real-world cases.
  • Simon Forsberg
    Simon Forsberg almost 11 years
    To use clazz2 instanceof clazz1 properly you can instead use class2.isAssignableFrom(clazz1), which I believe would return true in your example.
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 10 years
    Didn't read the 69 previous comments but I wholeheartedly give you a +1 - yes - wanting to override a static method is a quite valid requirement oftentimes. The problem is not unexperienced programmers btw - is mainly experienced ones - frustrated by the unability to define common behavior for all subclasses easily and elegantly - "the benefit of familiarity for C++ programmers", duh
  • Paolo Falabella
    Paolo Falabella over 10 years
    @user166390 scala's objects are not an equivalent of java "static classes". They are more the equivalent of what can be achieved in java with singleton or factory (but without all the boilerplate that these pattern require in Java). Note that you would be able to create equivalent code in java without static methods, except that it would be many times more verbose.
  • Mr_and_Mrs_D
    Mr_and_Mrs_D over 10 years
    Yes reflection is pretty much the only thing one can do - but the question is not exactly this - useful to have it here though
  • RichieHH
    RichieHH about 10 years
    This answer, while correct, is more akin to "how it is" rather than how it should be or more accurately how it could be in order to meet the expectations of the OP and, hence here, myself and others. There is no concrete reason to disallow the overriding of static methods other than "that's how it is". I think it's a flaw personally.
  • RichieHH
    RichieHH about 10 years
    Did you not read any of the other answer already covering this and making it clear that these are not reasons enough to discount overriding statics at the conceptual level. We know it doesnt work. It is perfectly "clean to desire the overriding of static methods and indeed it IS possible in many other languages.
  • RichieHH
    RichieHH about 10 years
    This is not true in a lot of instances where at runtime the static method is in fact called from an instance of the containing class and thus it's perfectly feasible to determine which instances of the function to invoke.
  • RichieHH
    RichieHH about 10 years
    There is nothing conceptually wrong with being able to call a static method through an instance. This is quibbling for quibbling's sake. Why should something like a Date instance NOT call its own static methods passing instance data to the function through the calling interface?
  • Athens Holloway
    Athens Holloway about 10 years
    Richard, let's assume for a minute that when I responded to this question 4 years ago most of these answers had not been posted, so don't be an ass! There is no need to assert that I did not read carefully. Furthermore, did you not read that we are only discussing overriding with respect to Java. Who cares what's possible in other languages. It's irrelevant. Go troll somewhere else. Your comment does not add anything of value to this thread.
  • cyc115
    cyc115 almost 10 years
    Very cool, it's the first time I have heard about the Haxe programming language :)
  • Pacerier
    Pacerier over 9 years
    @LawrenceDol, @StevePowell, That's not a problem because the compiler doesn't need to examine the instance at all. If parent.StaticMethod returns type C1, then child.StaticMethod is required to return an object of type C1 or subtype of C1. So the compiler knows for sure that the returned type is of (sub)type C1 and due to Liskov substitution principle there's no conflicts. Why do you say that there is a problem?
  • Lawrence Dol
    Lawrence Dol over 9 years
    This is much better implemented in Java as a static method on the class itself; Singleton.get(). The registry is just boilerplate overhead, and it precludes GC on the classes.
  • Lawrence Dol
    Lawrence Dol over 9 years
    No it doesn't; the static declared type of osm is OverridenStaticMeth not OverrideStaticMeth.
  • Lawrence Dol
    Lawrence Dol over 9 years
    Also, I'd try to avoid using so much Meth while programming <big grin>;
  • MT4000
    MT4000 over 9 years
    Your are right, it is a classic solution. I don't exactly remember why I chose registry, probably had some framework of thought which led to this result.
  • Rik Schaaf
    Rik Schaaf about 9 years
    @Jay if you replace return salary.multiply(getBonusMultiplier()); with try { Method m = this.getClass().getMethod("getBonusMultiplier"); return salary.multiply((BigDecimal) m.invoke(null)); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(Parent.class.getName()).log(Level.SEVERE, null, ex); } it does work. Makes me wonder: why does Java not support implicit reflection: return salary.multiply(origin.getBonusMultiplier());
  • Jay
    Jay about 9 years
    "If we did it would make method bodies harder to read: static calls in a parent class could potentially be dynamically "re-routed"." True, but this is exactly what happens with ordinary non-static function calls now. This is routinely touted as a positive feature for ordinary virtual functions, not a problem.
  • GrantRobertson
    GrantRobertson about 9 years
    @NathanHughes, This is a followup question: From your answer and others below, it seems that the reason why one cannot "override" a static method hinges upon the definition of the word "override," in Java. Because "override" means "change the behavior based upon the actual object datatype regardless of the reference datatype" and static methods, by definition, do NOT change the behavior from that in the reference datatype then one cannot SAY a static method with a matching signature in a subtype is overriding the supertype method. Thus, we SAY it is "hiding" the supertype method.
  • GrantRobertson
    GrantRobertson about 9 years
    Here is a followup to the above followup question: Assuming that my supposition above is correct, does that mean what people are really asking for is that there be a way for class methods to change their behavior dynamically based upon the datatype of the actual object? It does seem to me that this is working at cross-purposes. If one wants the behavior to change dynamically based upon the actual objects, then that means there WILL be objects upon which to call the method. So what would be the point of making said method a class method?
  • Nathan Hughes
    Nathan Hughes almost 9 years
    @GrantR: yes, there's an expectation people have that class methods work dynamically similar to smalltalk/ruby/python etc. here's an example for python at julien.danjou.info/blog/2013/…
  • DJClayworth
    DJClayworth almost 9 years
    Hi G4uKu3_Gaurav. Thanks for deciding to contribute. However we generally expect longer and more detailed answers than this.
  • g1ji
    g1ji almost 9 years
    @DJClayworth you should follow this link for detailed answer geeksforgeeks.org/…
  • DJClayworth
    DJClayworth almost 9 years
    Thanks for the link. Actually I'm here to be helpful to newcomers to the site, to explain how the site works for those who aren't used to it, not because I needed an answer to the question.
  • Nick
    Nick almost 9 years
    PHP 5.3+ have special way of override static method too - late static binding. But most PHP developers are not familiar with this feature anyway.
  • Michal M
    Michal M over 8 years
    Introduce some feature (especially when it makes reading the code more tricky but gives more power) in Scala and nobody bats an eye. Ask why it's not in Java and suddenly everybody loses their mind, telling you what a bad design that would be.
  • Eric
    Eric about 8 years
    @Jay When RegularEmployee instance call getBonusMultiplier(), it get 0.3, not 0.2, refer: ideone.com/fqmuks
  • Holger
    Holger over 7 years
    @Lawrence Dol: if you write B.someMethod() in your source code, the compiled code will refer B.someMethod(), not A.someMethod(), even if the method happened to be found in the super class A, so adding the method to B afterwards will cause the already compiled code to use B.someMethod() without the need to recompile. It seems to be a tenacious myth of static methods being bound at compile-time but they are bound at load-time (or link-time, if the JVM makes a difference between the two). There were compilers in the past (1.2 or earlier) which did it wrong, but that’s long ago
  • Jay
    Jay over 7 years
    @Holger Yes, true. But A b=new B(); b.someMethod(); executes A.someMethod, even though b is a B. That's the point under discussion.
  • Holger
    Holger over 7 years
    @Jay: Well, Lawrence referred to both scenarios and for the case that the source code refers to B.someMethod();, his statement had to be corrected. The case of writing instance.staticMethod() has already been widely discussed; I tend to say that the possibility to write it that way shouldn’t have existed in the first place, however, I don’t want to reopen that discussion.
  • Dmytro
    Dmytro over 7 years
    "A static method is not associated with any instance of a class so the concept is not applicable.". Nonsense, it is associated with the class itself, so it would make sense to have IBox have method "public static IBox createBox" which is overriden by "Box" object that implemented "IBox". Without this, we are forced to create "unnatural" factory classes, or resort to failing in constructors(as we cannot have static method return the object, and rely on constructor, which cannot return null, which promoted unnecessary exceptions). if Box could override createBox, it could eliminate all this.
  • Dmytro
    Dmytro over 7 years
    How is it counter intuitive to have an public abstract IBox createBox(); inside IBox interface? Box can implement IBox to override createBox, and have the creation of object result in a valid IBox, otherwise return a null. Constructors cannot return "null" and therefore you are forced to (1) use exceptions EVERYWHERE(what we do now), or (2) create factory classes that do what I said earlier but in a way that makes no sense to novices nor experts of Java(Which we also do now). Static unimplemented methods solve this.
  • Dmytro
    Dmytro over 7 years
    static does not mean compile time, static means that it is bound to class rather then any specific object. it makes as much if not more sense than creating a class factory, except static Box.createBox makes more sense than BoxFactory.createBox, and is an unavoidable pattern when needing to error check construction without throwing exceptions(constructors can't fail, they can only kill the process/throw exception), whereas a static method can return null on failure, or even accept success/error callbacks to write something like hastebin.com/codajahati.java.
  • PAULUS
    PAULUS over 7 years
    If you intend to override a method without using the @Override annotation, then you deserve all the problems that come your way because of it. It's a bad practice.
  • Andrejs
    Andrejs about 7 years
    This answer is the biggest hack I've seen so far across all Java topics. Was fun to read it still :)
  • slaman
    slaman over 6 years
    Re: "there had been a lot of criticism of Smalltalk about it being too slow". Note: Smalltalk ran on a 286 (1M of RAM). The garbage collection was slow on a 286 and first impressions stuck. Here's a reference from 1995 suggesting Smalltalk and C++ had similar performance for applications. jeffsutherland.org/papers/oocobol.html
  • Nathan Hughes
    Nathan Hughes over 6 years
    @slaman: there was criticism, I never said it was well-founded.
  • SQB
    SQB over 6 years
    Perhaps a better example would be valueOf(String s). I can imagine some interface "CanGetValueOfString" that would prescribe such a static method, to be implemented by the likes of Integer and Double and so on.
  • fishinear
    fishinear over 5 years
    @RichieHH That is not what they are quibbling about. The question is why is it allowed to call variable.staticMethod(), instead of Class.staticMethod(), where variable is a variable with declared type Class. I agree it is bad language design.
  • RichieHH
    RichieHH over 5 years
    They are allowed because the instance has access to all the static methods and so it should. It IS quibbling for quibbling's fault.
  • Dmitry Zagorulkin
    Dmitry Zagorulkin almost 5 years
    It's bad practice to call static methods from object.
  • WJS
    WJS almost 4 years
    Delphi (Object Pascal) was the first language implementing OOP. Simula, SmallTalk, and others supporting OOP and all came before Delphi.
  • Patlatus
    Patlatus almost 4 years
    @WJS I have never heard about Simula or other languages that supported OOP. I think Delphi was the first language implementing OOP used in commercial application development and wide-known. Looks like I need to rephrase this statement
  • kaiser
    kaiser over 3 years
    I don't think, one should argue "static" vs "dynamic" by its internal implementation. That's an language's API keyword. What is the programmer expecting? Static methods return constant results while running (for a specific class) => static. Member functions return results, depending on instance's variables (which can change while running) => dynamic.
  • user253751
    user253751 almost 3 years
    @Powerlord What appears to call a static method through an instance does not actually call the static method through the instance.