1

For the below code I got the output as

In Base.foo()  
In Derived.bar()

Code:

class Base {
    public static void foo(Base bObj) {
        System.out.println("In Base.foo()");
        bObj.bar();
    }  
    public void bar() {
        System.out.println("In Base.bar()");
    }
}
class Derived extends Base {
    public static void foo(Base bObj) {
        System.out.println("In Derived.foo()");
        bObj.bar();
    }
    public void bar() {
        System.out.println("In Derived.bar()");
    }
}
class OverrideTest {
    public static void main(String []args) {
        Base bObj = new Derived();
        bObj.foo(bObj);
    }
}

How the code flows? How I am getting the output as the above. I confused little bit and looking for the explanation.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
srinivasan
  • 11
  • 1
  • 5
    Static methods are not overriden. – Arnaud Jan 28 '16 at 10:25
  • 4
    What did you expect, and why? It's a lot easier to explain where your thinking is mistaken if you explain what that thinking is first. Note that you're calling a static method via a variable, which is a really bad idea to start with. – Jon Skeet Jan 28 '16 at 10:25
  • 1
    Possible duplicate of [Overriding static methods in java](http://stackoverflow.com/questions/16617408/overriding-static-methods-in-java) – Ross Drew Jan 28 '16 at 10:27
  • @JonSkeet Not even sure why that is allowed in Java. It only generates confusion. To his credit, he probably doesn't realize how to properly call a static method. – Neil Jan 28 '16 at 10:27
  • @Neil: Basically, it's a design flaw in Java, IMO. – Jon Skeet Jan 28 '16 at 10:29
  • Well i think the author of the topic just tried out one of these exercises in preparation for java professional certification. Therefore the use of the static method from the variable it may be confusing on purpose. – Rollerball Jan 28 '16 at 10:29
  • It's allowed @Neil because it's static, you can statically call it on either class. It's completely different. – Ross Drew Jan 28 '16 at 10:30
  • @JonSkeet why do you posit the fact that class-scoped methods are bound to compile time and not overridden is a design flaw in Java? Isn't that the same for C# by the way? – Mena Jan 28 '16 at 10:35
  • @RossDrew I know it's static. It doesn't require an instance to launch, although you *can* use one. I just fail to see how the usefulness of this overshadows the confusion created by this. – Neil Jan 28 '16 at 10:37
  • @Mena: Because it causes confusion - I've seen it in many, many cases, e.g. where someone calls `someThread.sleep(...)` and expects it to put that thread to sleep, rather than the *current* thread. And no, it's not the same in C# - you can't call a static method via an expression in C#. You'd have to call `Thread.Sleep` instead of `someThread.Sleep`. (And let's call them "static" methods instead of "class-scoped"... scope in the normal meaning of the word is somewhat orthogonal to this.) – Jon Skeet Jan 28 '16 at 10:38
  • Because it's attached specifically to the class. If you had a static `create()` factory like method, you could have it on `Base` and `Derived` and expect to call it specifically on each class and expect different behavior. – Ross Drew Jan 28 '16 at 10:39
  • @JonSkeet I think I understand your point now. The design flow would be being able to invoke a `static` method on an instance object - I thought you were challenging the fact `static` methods are not overridden :) – Mena Jan 28 '16 at 10:40
  • @RossDrew And when I see things like baseClass.create() and the Derived class create() gets called instead, it makes me want to scream. If you interpret one behavior in the code you read and it does another, it should be avoided for clear and concise code. I don't want to have to check if create() is a static method to know which is being called. – Neil Jan 28 '16 at 10:42

2 Answers2

3

Static methods are not overridden, there's no virtual invocation.

In your Derived class, the static foo method is hiding its parent class' static foo method.

However, in your main method, you are invoking foo on a reference type Base, hence Base#foo gets invoked (so it prints "In Base.foo()").

In turn, the static method invokes bar on the passed object, which IS-A Base, but happens to be an instance of Derived.

Since bar is an instance method and is overridden given your signature matches, the invocation resolves to the instance type, which is Derived, hence "In Derived.bar()" is printed.

Notes

  • A good practice is to employ the @Override annotation on overridden methods. This would fail to compile for your foo method as it's static, thus clearly pointing out there's no possible overriding there.
  • Another good practice (as pointed out by Jon Skeet) is to avoid invoking static methods on instance objects (i.e. prefer an explicit ClassName.staticMethod idiom), as this may cause confusion on the scope in which the method is invoked.
Community
  • 1
  • 1
Mena
  • 47,782
  • 11
  • 87
  • 106
  • I'd add that it's also good practice not to call static methods like this, but instead specify the class name. – Jon Skeet Jan 28 '16 at 10:39
0

Code flow will be like

Base bObj = new Derived();

Here you are creating the bObj with type Base and the runtime object will be of class Derived.

bObj.foo(bObj);

as foo() is a static method and static binding happened at compile time so it will not check for the runtime object type.So as you are declaring a Base type object ,the method in Base will get executed.Inside that function you are calling non static methos bar() with the object argument.The object passed at runtime is your Derived class instance ,hence it will be called.