Tips and Tidbits from someone Sun felt was Certifiable

Today | ???common.rss??? | ???common.rdf??? | ???common.atom??? | ???common.other???
 

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.


I say if you call static methods via instances instead of ClassName.staticMethod, the long and short of it is that you're wrong, too. I think if people didn't use instances to call static methods, this problem wouldn't be such a big deal.
You CAN'T have an overridden default method either. I have seen people trying to overide default methods.Its no wonder when you have articles(by Bill Venners/Bruce Eckel) that begin with: "In Java, instance methods are virtual by default—they can be overridden in subclasses unless they are explicitly declared final. " - http://www.artima.com/intv/nonvirtual.html
DaveJ, you might want to rethink your statement a bit, there. You CAN override default methods (I'm assuming you're referring to methods with the default access modifier). Try out this code:

---------------------------------------
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.
Corey , you might want to rethink your statement a bit, there - You can override default methods ONLY if they share the same package. package a; class Super{...} package b; public class Sub extends a.Super{...
"You can override default methods ONLY if they share the same package."

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.
Corey>'Likewise, you can never override a private & default methods as they are not inherited.

Wrong again.Private & default methods are inherited - they are just not visible.
"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.
Perhaps, DaveJ, you're getting confused with inheritance in C++. It's been years since I've done any real work in C++, but I seem to think that, in that language, private members are inherited, but not accessible. I could be wrong about that, though - Like I said, it's been a couple years since I've looked at C++.
Last week a consultant, getting paid $50/hr, spent 10 minutes explaining a Java problem he was having to me. In the end, the problem was that he didn't know that static methods could not be overridden; and by-and-large didn't understand polymorphism. This is the kind of crap that drives me nuts. I see many people talking about the SCJP being "pedantic", but this is a case in point where anyone charging for Java development should just get the cert and be done with it.
yes
Static Method definitly can be overriden. The only constraint is that it does not suppport polymophism.
Good.
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.

Yes. i agree with Corey. There is one simple statement about overriding. "Only instance methods can be overridden" . Thats it !!
Static methods are only hidden and not overridden. But I believe, the overriding rules apply even for static methods when you declare the static method in the subclass. (overriding rules like return type, throws clause etc).
TrackBack to http://radio.javaranch.com/corey/addTrackBack.action?entry=1079739453000