Behaviour of final static method

54,079

Solution 1

Static methods cannot be overridden but they can be hidden. The ts() method of B is not overriding(not subject to polymorphism) the ts() of A but it will hide it. If you call ts() in B (NOT A.ts() or B.ts() ... just ts()), the one of B will be called and not A. Since this is not subjected to polymorphism, the call ts() in A will never be redirected to the one in B.

The keyword final will disable the method from being hidden. So they cannot be hidden and an attempt to do so will result in a compiler error.

Hope this helps.

Solution 2

static methods cannot be overriden

This is not exactly true. The example code really means that the method ts in B hides the method ts in A. So its not exactly overriding. Over on Javaranch there is a nice explanation.

Solution 3

Static methods belong to the class, not the instance.

A.ts() and B.ts() are always going to be separate methods.

The real problem is that Java lets you call static methods on an instance object. Static methods with the same signature from the parent class are hidden when called from an instance of the subclass. However, you can't override/hide final methods.

You would think the error message would use the word hidden instead of overridden...

Solution 4

You might find yourself in the position to think about making a static method final, considering the following:

Having the following classes:

class A {
    static void ts() {
        System.out.print("A");
    }
}
class B extends A {
    static void ts() {
        System.out.print("B");
    }
}

Now the 'correct' way to call these methods would be

A.ts();
B.ts();

which would result in AB but you could also call the methods on instances:

A a = new A();
a.ts();
B b = new B();
b.ts();

which would result in AB as well.

Now consider the following:

A a = new B();
a.ts();

that would print A. That might surprise you since you are actually having an object of class B. But since you're calling it from a reference of type A, it will call A.ts(). You could print B with the following code:

A a = new B();
((B)a).ts();

In both cases the object you have is actually from class B. But depending on the pointer that points to the object, you will call method from A or from B.

Now let's say you are the developer of class A and you want to allow sub-classing. But you really want method ts(), whenever called, even from a subclass, that is does what you want it to do and not to be hidden by a subclass version. Then you could make it final and prevent it from being hidden in the subclass. And you can be sure that the following code will call the method from your class A:

B b = new B();
b.ts();

Ok, admittetly that is somehow constructed, but it might make sense for some cases.

You should not call static methods on instances but directly on the classes - then you won't have that problem. Also IntelliJ IDEA for example will show you a warning, if you call a static method on an instance and as well if you make a static method final.

Share:
54,079
Harish
Author by

Harish

Updated on February 08, 2022

Comments

  • Harish
    Harish over 2 years

    I have been playing around with modifiers with static method and came across a weird behaviour.

    As we know, static methods cannot be overridden, as they are associated with class rather than instance.

    So if I have the below snippet, it compiles fine

    //Snippet 1 - Compiles fine
    public class A {
        static void ts() {
        }
    }
    
    class B extends A {
        static void ts() {
        }
    }
    

    But if I include final modifier to static method in class A, then compilation fails ts() in B cannot override ts() in A; overridden method is static final.

    Why is this happening when static method cannot be overridden at all?

  • Sean Owen
    Sean Owen over 14 years
    I don't think this explains why 'final' suddenly means these methods can't coexist. As you say, without 'final', there's no problem. You say it's not overriding, but then say the problem is that B can't override A's method.
  • Sean Owen
    Sean Owen over 14 years
    To perhaps finish your answer, which is right I believe, the problem here is basically a bad compiler error message: it should says B cannot hide ts() in A. Declaring a static method final is declaring it cannot be hidden.
  • eric-hunter
    eric-hunter over 14 years
    Sure it does, I state that B does not see the method ts() in A (it is 'hidden'), but the final modifier does not 'hide' methods from classes that extend another one. But eh, ok.
  • NawaMan
    NawaMan over 14 years
    @Sean Owen: I think so too. The term 'hide' is even used in Java Specification so why not use it in the compiler message.
  • John Mercier
    John Mercier over 9 years
    It is true just not precise. static methods cannot be overridden but can be hidden if you are calling them on a instance reference rather than the class name.
  • user253751
    user253751 over 9 years
    Why is this even a feature? In what context would it be useful?
  • srikanth r
    srikanth r over 8 years
    public class Test { final static public void main(String... srik) { System.out.println("In main method"); ts(); } public static void ts() { Child c=new Child(); c.ts(); System.out.println("Test ts"); } } public class Child extends Test { public static void ts() { System.out.println("Child ts"); } } Hi Can u plz explain me what happens in this scenario
  • Koray Tugay
    Koray Tugay about 7 years
    So you consider the static method in B overriding the one in A?
  • Mathias Bader
    Mathias Bader almost 7 years
    Unfortunately your link isn't working any more. Is it possible to fix this?
  • Eugene
    Eugene about 6 years
    @SeanOwen I don't think this is correct either, the compiler should say that since A#ts is being inherited and such a method already exists in B, simply having two methods with the same signature and a different modifier (final) would not work as overloads... I wish I could think of a simple message for this, though
  • Eugene
    Eugene about 6 years
    @KorayTugay I just wonder if the compiler first looks at the potentially overridable method (ignores static for a moment), sees final at fails. Just a wild guess though
  • Koray Tugay
    Koray Tugay about 6 years
    Balus I think this is the only low quality answer you have in StackOverflow. Considering all your exceptional answers, this one does not belong to them. @BalusC
  • BalusC
    BalusC about 6 years
    @KorayTugay: at that time I didn't had enough reputation to comment :) If you ping back, I'll delete the answer, no problem.
  • Sundeep
    Sundeep over 5 years
    The javaranch link isn't working, but Googling the key words turned up this link on code ranch
  • MC Emperor
    MC Emperor about 5 years
    I've edited the post by replacing the dead link by the link posted by Sundeep.
  • Michael
    Michael almost 4 years
    My book "java how to program edition 10" says static methods are implicitly final (chapter 10.7). prntscr.com/u3too3 If static methods are final, and if final methods cant be hidden. That means static methods shouldn't be hidden aswell. But we are able to hide static methods.
  • Scratte
    Scratte almost 4 years
    "But they are inherited like static and non-static data members." I do not think so. They are accessible from the child class, but that is not the same as inherited. "final keyword restricts the creation of method with the same name in the child class." is also not correct. You can overload a static final method in a child class. You just can't create a method with the same signature.
  • Scratte
    Scratte almost 4 years
    I think perhaps your phrasing "should not be overridden in B" could be changed to "should not be hidden in B"