views:

350

answers:

6

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?

+16  A: 

Static methods cannot be overridden but they can be hidden. ts() method of B is not overridden (not subject to polymorphism) ts() of A but 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.

NawaMan
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.
Sean Owen
@Sean Owen: I think so too. The term 'hide' is even used in Java Specification so why not use it in the compiler message.
NawaMan
+4  A: 

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.

Vincent Ramdhanie
A: 

The ts() method in B is not overriding the ts() method in A, it simply is another method. The B class does not see the ts() method in A since it is static, therefore it can declare its own method called ts().

However, if the method is final, then the compiler will pick up that there is a ts() method in A that should not be overridden in B.

amischiefr
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
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.
amischiefr
+2  A: 

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

R. Bemrose
A: 

Not an answer. But isn't this an issue because language (Java, in this case) allows calling a static method via an instance variable?

shahkalpesh
No, don't think that's relevant here. The method is not being invoked at all, from instance or not.
Sean Owen
@Sean Owen: Actually... it is relevant, because of how the final keyword works on methods.
R. Bemrose
+1  A: 

I think the compilation error was quite misleading here. It should not have said "overridden method is static final.", but it should instead have said "overridden method is final.". The static modifier is irrelevant here.

BalusC