[SCJP Tips] [SCJP Tips: Overloading, Overriding, Runtime Type and Object Orientation] Static Methods CAN NOT be Overridden
I hear people say it all the time..."I've got this static method that is overridden in my child class..." The long and short of it is that you're wrong - you don't have an overridden static method because you CAN'T have an overridden static method.
Let me quote the JLS, in section 8.4.6.2 Hiding (by Class Methods), it states:
"If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class."
So, now let's look at what that means, shall we?
class Parent
{
public static void myStaticMethod()
{
System.out.println("A");
}
public void myInstanceMethod()
{
System.out.println("B");
}
}
public class Child extends Parent
{
public static void myStaticMethod()
{
System.out.println("C");
}
public void myInstanceMethod()
{
System.out.println("D");
}
public static void main(String[] args)
{
Parent o1 = new Parent();
Parent o2 = new Child();
Child o3 = new Child();
Parent.myStaticMethod(); // A
Child.myStaticMethod(); // C
o1.myStaticMethod(); // A
o1.myInstanceMethod(); // B
o2.myStaticMethod(); // A
o2.myInstanceMethod(); // D
o3.myStaticMethod(); // C
o3.myInstanceMethod(); // D
myStaticMethod(); // C
myInstanceMethd(); // Compiler Error
}
}
I have included the output next to each line so that you can see exactly what gets invoked. Pay particular attention to the methods invoked on the variable o2.
Notice that o2.myStaticMethod invokes Parent.myStaticMethod(). If this method were truly overridden, we should have invoked Child.myStaticMethod, but we didn't. Rather, when you invoke a static method, even if you invoke it on an instance, as we did here, you really invoke the method associated with the "compile-time type" of the variable. In this case, the compile-time type of o2 is Parent. Therefore, we invoke Parent.mStaticMethod().
However, when we execute the line o2.myInstanceMethod(), we really invoke the method Child.myInstanceMethod(). That's because, unlike static methods, instance methods CAN be overridden. In such a case, we invoke the method associated with the run-time type of the object. Even though the compile-time type of o2 is Parent, the run-time type (the type of the object o2 references) is Child. Therefore, we invoke Child.myInstanceMethod rather than Parent.myInstanceMethod().
Be sure to check out the JLS and what it has to say about overriding vs. hiding.
---------------------------------------
class Super
{
void doIt()
{
System.out.println("Super.doIt()");
}
}
public class Sub extends Super
{
void doIt()
{
System.out.println("Sub.doIt()");
}
public static void main(String[] args)
{
Super s = new Sub();
s.doIt();
}
}
// Output
Sub.doIt()
---------------------------------------
As you can see, the above method, doIt(), has the default access modifier and is overridden.
I took that to be a given. In order to override a method, the method must first be inherited. If the method is not inherited (which it is not if the extending class is not in the same package), there is no chance for overriding. Likewise, you can never override a private method as they are not inherited.
Wrong again.Private & default methods are inherited - they are just not visible.
From the JLS, §8.2 Class Members:
"Members of a class that are declared private are not inherited by subclasses of that class."
Public and protected members are inherited by all subclasses while default (or package) members are inherited only by subclasses within the same package. Private members, however, are not inherited, as shown by the JLS.
Static Method definitly can be overriden. The only constraint is that it does not suppport polymophism.
That's just not accurate. Take a look at that quote I pulled from the JLS:
If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class.
So it's not called "overriding", it's called "hiding". Overriding a method implies polymorphic behavior and, as you said, static methods do not exhibit polymorphic behavior.
Another blurb from the JLS (§8.4.6.1 Overriding (by Instance Methods)), goes on to say this about overridden methods:
An overridden method can be accessed by using a method invocation expression (§15.12) that contains the keyword super.
That doesn't work with static methods as static methods can be invoked without any instance of a class, whatsoever. Therefore, the keyword super can not even be used. So, this is just another way in which a hidden method is different from an overridden method.
People may call it a "nit-pick", but the SCJP exam is about knowing proper terminology and, quite simply, a static method with the same signature of a static method in the superclass is said to hide that method, not override it.
