Tuesday, June 3, 2008

Can you override Static Methods in Java?


Question: Can you override Static Methods in Java?


Answer: Well... the answer is NO if you think from the perspective of how an overriden method should behave in Java. But, you don't get any compiler error if you try to override a static method. That means, if you try to override, Java doesn't stop you doing that; but you certainly don't get the same effect as you get for non-static methods. Overriding in Java simply means that the particular method would be called based on the run time type of the object and not on the compile time type of it (which is the case with overriden static methods). Okay... any guesses for the reason why do they behave strangely? Because they are class methods and hence access to them is always resolved during compile time only using the compile time type information. 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 :-)


Example: let's try to see what happens if we try overriding a static method:-


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

...

}


}


Output:-


SuperClass: inside staticMethod

SuperClass: inside staticMethod

SubClass: inside staticMethod


Notice the second line of the output. Had the staticMethod been overriden this line should have been identical to the third line as we're invoking the 'staticMethod()' on an object of Runtime Type as 'SubClass' and not as 'SuperClass'. This confirms that the static methods are always resolved using their compile time type information only.


Liked the article? You may like to Subscribe to this blog for regular updates. You may also like to follow the blog to manage the bookmark easily and to tell the world that you enjoy GeekExplains. You can find the 'Followers' widget in the rightmost sidebar.



Share/Save/Bookmark


29 comments:

saddy said...

As per the article, I do agrre what you have written. I just want to add a line that, " You can not override the static method because as per the nature of static method it belongs to specific class, but you can redeclare it in to the subclass but that subclass doesn't know anything about the parent class' static methos because as I said it is specific to only that class in which it has been declared. "

Geek said...

Thanks for your inputs, Saddy. You're right in saying that static methods belong to the particular class, but I think you may like to re-consider the second part which says "... that subclass doesn't know anything about the parent class' static methods". I think a sub class will always know all accessible members/methods of its super class whether it's a static member/method or an instance member/method.

Irrespective of whether a method is an instance method or a static method, the object reference of a sub class needs to be casted to the super class for that method to be called on the object reference if the same method is not overridden (in case of an instance method) or re-declared (and hence the super class version of the method is hidden by the subclass version) in the sub class. Having said that an accessible static method is known as much to the sub class as an accessible instance method.

The main difference being the way an instance and a static method call are resolved. The former is resolved at run time whereas the latter is resolved at compile-time. All right?

Anonymous said...

well said geek,I agree to the point

Guilherme Garnier said...

Shouldn´t static methods not be called from objects, just from classes?

Geek said...

Certainly Yes. I've also been saying the same.

During compilation any obj-ref based static method call would be changed into a call made on the declared type of the reference only.

Therefore, if we directly call static methods on class names then we will not only save compiler from finding the declared type, but will also (and more importantly) make the code more readable and understandable.

Rajarshi said...

hi...

I really appreciate what you said of the article but when i tried it, it is not even passing the compiler( i mn its givin compilation error!) its not allowing us to override a static method of parent class

Geek said...

Rajarshi, can you please share the code you're trying with? Did you try the one I've given in the article? If yes, then please make sure that you have removed all the dotted lines as they are just placeholders for any valid custom code someone might want to put as per their wish. If not, then your code would probably be having some other issue(s), which I can comment upon only when I see it :-)

Anonymous said...

Good one Geek...Appreciate your effort in explaining it very crisply.

ALIV N NJOIN said...

Hey!

First of all sorry for not checking your blog for a long time. Well i did not try the code written above but when i tries to override a static method the method which of subclass which was overriding was not marked as static so the IDE was giving compilation error.It was something like this

public class synonymResolver{
......
public static void resolveSynonyms(){..}
}//end of class

public class specificsynonymResolver extends synonymResolver{

public void resolveSynonyms{} //compilation error
}

Geek said...

The error is being thrown because an instance method can't override a static method of super class.

The reason why Java doesn't allow this is that if allowed it would cause ambiguity. Let's understand it with your code-snippet:-

//super class ref for a sub class obj - valid
synonymResolver superRef = new specificsynonymResolver();

//method call on the ref - ambiguous, right?
superRef.resolveSynonyms();

Now, as we know that static methods are resolved at compile-time whereas instance methods at run-time, what should the compiler do here? Evidently it's an ambiguous situation to be in and hence NOT ALLOWED! Makes sense?

Rajarshi said...

Thank you...! So since it is resolved at compile time so whenever we refer a subclass obj by a superclass reference the static method of the super class is called....right??

Another question why did the designers of the language decide that the resolution should be done at compile but not at run time....I know the question sounds weird but any reasons you know!

Thanks
Rajarshi

Geek said...

Yes. Since static method calls are resolved at compile-time so compiler picks the method based on the declared type of the reference only and not by the actual type of object it would point to.

Before I try to answer your next question, let me tell you that it's certainly not a weird one.

I hope you would agree with the point that compile-time binding will always make the code little faster as the run-time type info and other required steps for run-time binding get avoided here. So, why didn't they think of only compile-time binding? Because in that case they couldn't have supported an essential feature called 'Run-time Polymorphism' and this could certainly have reduced the capability of the language.

So, they probably went with the idea that whenever all the required info for an unambiguous method resolution is available at compile-time, the method would be bind that time only. Otherwise the binding would happen at run-time.

As you know, static methods are class methods (having access to only class members i.e., static members) and even though syntactically one may call them on object references, they are noway influenced by particular objects (and hence it's not advised to call them on object references - this makes the code better readable).

Since the compiler has all required info for their resolution available at compile-time itself so no point deferring the binding to happen at run-time. Makes sense?

Thanks for your active participation and I hope the discussion will only help other readers to gain/contribute more on the topic. Keep posting!

Rajarshi said...

Yes absolutely if you can do resolve at compile time then why do it at run time !
nice answer
Thanks
Rajarshi !

pawan said...

this is really satisfied answer.
thanks and keep this blog up.
But i know that object of the class can not call the static method.
it is the class itself which can access the static methods.
If it has been deprecated than please confirm the same.

Thanks and regards
pawan sahu

Geek said...

Not sure if I understood your query correctly... but, yeah you can certainly call a static method on an instance/object of that class as well as you can call them directly by using the Class Name.

I think deprecation happens to the methods and not to the ways you can call them. However, I personally feel calling static method on Class Names is probably the better way. HTH.

Kutty said...

Super Explanation. we can able to understand difference between overriding and hiding from this.

Name Does it matter?? said...

Can some one please explain why the following code doesnot work?

public class Parent {
public static void method1(){
System.out.println("in aaaa");
}
}

public class Child extends Parent{
public static void method1() throws FileNotFoundException{
System.out.println("in bbbb");
}
}


It throws an exception Exception FileNotFoundException is not compatible with throws clause in Parent.method1() in the child class.

Thanks

Nikunj

Geek said...

Nikunj, I guess you have answered it yourself in the last para of your comment.

Putting it differently, JLS clearly says that "A method that overrides or hides another method (§8.4.6), including methods that implement abstract methods defined in interfaces, may not be declared to throw more checked exceptions than the overridden or hidden method."

Hope this helps.

Anonymous said...

Can we create a instance for accessing static methods?
As per my knowledge we don't create an instance for accessing static methods?
by class name only we access static methods(classname.staticmethodname)
am i correct?

Geek said...

Yes, you can call a static method on an instance (in addition to calling them on class names). Usually the better approach is calling them on class names though.

In the above article I've called static methods on instances to show that they can not be overridden and in the example I've tried to be as close to overriding implementation for instance methods to compare the behavior.

swati said...

Very clear and well explained logic .
The queries put forth by other co-readers helped a lot to understand the concept in greater depth.

Javin @ spring interview questions answers said...

Good stuff, just to add While doing concurrent programming avoid using static keyword as much as possible as it's shared between all instances and all threads and create subtle issues if not synchronized properly. I have also shared my view as 10 Points on Static in Java let me know how do you find it.

SkaRootz said...

I just want to quote this explanation:

...quoting...
Nikunj, I guess you have answered it yourself in the last para of your comment.

Putting it differently, JLS clearly says that "A method that overrides or hides another method (§8.4.6), including methods that implement abstract methods defined in interfaces, may not be declared to throw more checked exceptions than the overridden or hidden method."

Hope this helps.

...quoting...


Woah good explanation for the weird situation I was against...

Umer Khan said...

hey one question,


In which scenario we should override static method ? is there any particular example ?

Geek said...

there should hardly be any compelling reason to hide (as explained in the article you don't really override, but can only hide static methods in sub-classes) a static method... if you get into such a situation you may like to review your class/app design... more often than not hiding static methods makes the overall application code less readable...

Anonymous said...

Very useful and straight forward article.

Actually, static method are not overridden but redefined. This is the term, just in case anybody cares about this. And as the author said the decision is taken at compile time.

atinder singh said...

I found your explanation quite useful and clear,Thanks.

Avi said...

The static member definitions of a variable type are resolved by the type of the variable. The type of the variable is its own type or the type it is casted to.
Whereas the non-static member definitions of a variable are resolved by the sub-type the variable is assigned to.
Hence the non-static member definitions of a variable get overridden, whereas the static member definitions don't.

leeja john said...

Agree to your blog , this is the most searchable topic on these days .
I have also described static variable in a simple form .

http://efectivejava.blogspot.in/2013/08/when-to-use-static-members-in-java.html