How Does the JVM handle Dynamic Dispatch in this Situation? - java

Given the following source and ouput:
Source:
public class A
{
public void foo()
{
bar();
}
public void bar()
{
System.out.println ("in A's bar() method");
}
}
public class B extends A
{
#Override
public void foo()
{
super.foo();
// Do some specialized B stuff
}
#Override
public void bar()
{
System.out.println ("in B's bar() method");
}
}
public class Main
{
public static void main (String... args)
{
B b = new B();
b.foo();
}
}
Output:
in B's bar() method
Can someone please explain to me how the JVM is smart enough to polymorphically call B's (as opposed to A's) bar() method in this situation? I'd like to know what kind of dynamic dispatch magic is going on behind the scenes here.
Update: In case I wasn't clear enough, I know basically WHAT is happening, I'm looking for specific details on HOW the JVM makes it happen under the hood. The answers so far are too simplistic.
Update 2: Maybe I wasn't clear enough. When b.foo() is called, then super.foo() is called, then bar() is called in class A's foo(). How does the bar() that is called when specifically invoking super.foo() not call class A's bar() method, since the super keyword explicitly specifies class A? What steps does the JVM have to go through to sort this out?
Also, does this mean it's a bad idea in general to call public methods from within their own class since they can be overridden in this way?

Java uses the object's type when invoking the methods.
A b = new B();
b.foo();
Let's say you used above code.
Here what will happen is you are creating an object of type B and assign it to a reference of type A. Since the object type is B, you'll invoke the method in class B.

Even if the constructor or method you're currently in is defined in a super-class, the object doesn't change type. It will still be an object of type B. This can be demonstrated by using the this keyword.
this refers to the current object. That is not the same as the class defining the current method or constructor.
Try typing the following into A's constructor or in the foo() method:
System.out.println(this.getClass());

The function call sequence is (from eclipse debug view):
1. B.foo() // super.foo()
2. B(A).foo() // bar()
3. B.bar()
After the thread calls super.foo(), the JVM will check if there's any implementation in B (since we still hold B.class in the stack), if there is, JVM will call it.
This feature is guaranteed by JVM implementation. It is not smart, it just be designed this way, just like C++'s virtual methods.
Hope it helps.

Related

Using super.method() when you're not overriding the method?

Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
Assume
public class Parent{
public void method() {
}
}
So
public class Child extends Parent {
public void someMethod() {
super.method();
}
}
or
public class Child extends Parent {
public void someMethod() {
method();
}
}
Thanks for your input.
Calling super tells the JVM to explicitly look to the parent class' version of a method. Continuing with your example, if you just call
method()
The JVM will first search in the calling class for the method (in this case Child) before looking at the parent class. On the other hand, if you call
super.method()
then the JVM will explicitly look at the parent class for an implementation, even if Child has an method called method().
Putting these two ideas together, you should probably always use super when you intend to call the parent class' method. If your class does not override the method, then you could call without super. But even this becomes problematical if someone were to refactor your class later on and override the method.
The leading question is easy to answer:
Is it common practice to always use super for calling methods out of the superclass, even when I'm NOT overriding the method?
No, its not common practice. On the contrary, its dangerously confusing to do so. You call methods normally, because the main point of inheritance is to allow the classes to override methods to change/extend their behavior. You normally don't care about at which level a method is actually implemented.
The obvious exception is when you do override the method yourself and you want/need the parents functionality.
Now to the dangerously confusing part of explicitly calling super:
public class CallSuper {
static class Parent {
public void foo() {
System.out.println("Parent.foo");
}
/**
* Calls foo to do the main work
*/
public void bar() {
System.out.print
foo();
}
}
static class Child extends Parent {
public void foo() {
System.out.println("Child.foo");
}
public void bar() {
super.foo();
}
}
static class GrandChild extends Child {
public void foo() {
System.out.println("GrandChild.foo");
}
}
public static void main(String[] args) {
Parent p = new Parent();
Parent c = new Child();
Parent g = new GrandChild();
System.out.print("Parent.foo() = ");
p.foo();
System.out.print("Child.foo() = ");
c.foo();
System.out.print("GrandChild.foo() = ");
g.foo();
System.out.print("Parent.bar() = ");
p.bar();
System.out.print("Child.bar() = ");
c.bar();
System.out.print("GrandChild.bar() = ");
g.bar();
}
}
If you run this example it will output (added line numbers for clarity):
1 Parent.foo() = Parent.foo
2 Child.foo() = Child.foo
3 GrandChild.foo() = GrandChild.foo
4 Parent.bar() = Parent.foo
5 Child.bar() = Parent.foo
6 GrandChild.bar() = Parent.foo
The first four lines are not surprising, we get what foo implements at each level, respectively Parents's bar calling its foo. It starts to get odd at line 5. Child bypasses its own override of foo by calling super.bar(), so while its foo() is specialized, bar() is not. In Line 6, you see that GrandChild inherits this oddity from Child, so the somewhat innocent looking super.foo() in Child's bar has now broken GrandChild's expectations that its override of foo() is effective for all bar() as well.
Now if you imagine foo() and bar() actually doing something useful and that they have a meaningful relationship with each other, e.g. you are led to believe (either by Parent's documentation or just common sense) that overriding foo() will change the behavior of bar(), too. Child's "super" is breaking that.
As a rule of thumb, if you see a "super.x()" call anywhere outside of an actual override of "x()", its probably an accident lurking to happen.
Is it common practice to always use super for calling methods out of the superclass? Or is it redundant code?
It's not redundant. It have a special purpose of invoking parent class method (though you ovveriden). When you don't want, don't invoke. If you current class is not child of that class, super won't work for you.
Also if you call an overridden supermethod, does it use the supermethod or the lowest method?(in the inheritance tree)
The overridden method. Since you overridden it in your class.
If you're not overriding, let's talk about performance.
If you call an inherited method in your class, let's say, methodInSuperclass(), the JVM will look for that method first in your class, then up the class hierarchy until it finds it.
Using super.methodInSuperclass() tells the JVM to go directly to the superclass to look for that method.
So, using the super keyword improves performance by a few mills. It's ugly code, but it's not redundant as it will bring some performance improvement.
Consider using it if time is critical.
Calling the super method or not depends entirely on what you are trying to do. If you want to do what the parent class did plus some additional action, then calling the super method is good. If you're doing something completely different in the child implementation then do not call the super method. When you do call the super method in a hierarchy of classes, it calls the one closest to your child class in the hierarchy.
In some cases you may have an API where calling the super method is part of the overall contract. The clone method is such a case.
If Child is having the same version method with Parent, JVM will call the Child's version instead of Parent's version if without "super". The "super" keyword is helpful if you want to make sure the Child is always calling the Parent's version method.

Java Interfaces and inheritance

I have a very basic doubt about Java Interfaces and inheritance.
Suppose I have two classes A and B and one interface C with following definitions
interface C{
public void check();
}
class A implements C{
public void check(){
System.out.println("A");
}
}
class B extends A implements C{
// Is the following method overriding the method from class A or implementing the method from C?
public void check(){
System.out.println("B");
}
}
I am confused that whether it is over-riding or implementation of check() method in class B?
It does both, they are not mutually exclusive. The purpose of an interface is to define a method signature that should be available inside the implementing class.
You should annotate the method with #Override though, it's just good form because it makes clear that it comes from a baseclass and it'll guard you against accidental typos.
As #Jeroen Vannevel and #EJP have mentioned above it's both overriding and implementing.
In order to understand this I think you need to see it in the context of compile/run time.
You have the following possible scenarios:
C c = new B();
c.check();
At compile-time you see C#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
A a = new B();
a.check();
At compile-time you see A#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
B b = new B();
b.check();
At compile-time you see B#check() (you can use your IDE to get you where c.check() points to) at runtime you see the overridden B#check()
If alternatively you are passing the method call directly in a method:
someMethod(new B().check())
then this equates the last of the above scenarios
It is both over-riding and implementing.
In your example:
class B extends A implements C{
// Is the following method overriding the method from class A or implementing the method from C?
public void check(){
System.out.println("B");
}
}
You are defining the check method in interface C as:
public void check(){
System.out.println("B");
You are allowed to do this as interfaces don't contain the definition of the method in the interface when they are created and can thus be used over and over again for things which are similar enough to use the same method with a few tweaks.

Why doesn't Java allow hiding static methods by instance methods?

As shown in http://docs.oracle.com/javase/tutorial/java/IandI/override.html, Java does allow
Overriding an instance method by an instance method and
Hiding a static method by a static method
My question is why Java doesn't allow hiding a static superclass method by an instance method. This could be done like this:
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {}
void access () {
foo ();
Base.foo ();
}
}
I don't see any particular issue with the above approach - it is only as "messy/complex" as the (allowed) hiding of statics already is.
I suspect it is to avoid confusion with dealing with the base class. In fact I imagine the designers didn't see an obvious way this should behave.
class Base {
static void foo () {}
}
class Derived extends Base {
void foo () {} // say this compiled
}
Base b = new Derived()
b.foo(); // should the static or the virtual method be called?
Should b.foo() call Base.foo() or should it potentially call Derived.foo()?
Simple answer: that would be the mess.
Concrete answer: what to call in that case Derived.foo()? Base.foo() can't be called as it's hidden (as per you), Derived.foo() can't be called as it's not static.
Because, one are like Bananas and the other ones are Apples.
Explaination:
Static Methods are created when reading the Class-Structure
Methods are created when a object of a class is created.
Example:
Foo.bar();
is something different than
new Foo().bar();
Guess which one is called?
Foo f = new Foo();
f.bar();
Another to add here is:
1. Static methods belong at the class level. So u cannot override method in the derived class.
as simple its called hiding. :)
2. Instance methods belong to the objects, so objects are overrided. So we can override in the derived class.
Above other comments give a good example have a look into it..
Regards
Punith

Why output in this order?

abstract class A {
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
public abstract void methodB();
public void showName() {
System.out.println("in showname base");
}
}
class B extends A {
public void methodB() {
System.out.println("methodB");
}
public void showName() {
System.out.println("in showname child");
}
}
public class SampleClass {
public static void main(String[] args) {
A a = new B();
a.methodA();
}
}
Output is :
methodA
methodB
in showname child
Question :-
Since in overriding, the object type is considered. Is it the reason behind that class B's showName() method called not of class A's? If not then whats the cause of this output order?
You created an object of type B, so all methods called on that object will be on class B. If class B does not implement some methods (like methodA), then Java tries to find a method in the parent class (A). You should read about polymorphism in object oriented languages:
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
It's easy:
A a = new B();
a.methodA();
here is known that a is object of B class, so every method that can be overriden in class B is used from class B if there is no overriding, then method from class A must be used.
Considering order:
you invoke methodA that is declared as:
public void methodA() {
System.out.println("methodA");
methodB();
showName();
}
from inside of methodA() you invoke both methodB() and showName(). They are overriden in class B, and object a is instanceof B, so that's why they (from B class) are used.
EDIT as mentioned in comment:
#Jaikrat Singh, class B is still class A (child of it, but inheritance is relation of type: IS-A ). Class B has inherited methods from A class. So it has methodA as well. So it's better to say, that methodA is also called from class B but with is default code - the same as provided in class A
While the object 'a' is declared as type A, it is instantiated as type B. Polymorphism causes the methods of the instance type to be called rather than those of the declaration type, so because it is internally of type B, the showName() method of class B is called.
When you call a.methodA(), since your object type is B, it will look for methodA first in B. Since there is no such method in B, it will look for this method in its super class, which is A. Finding methodA in class A, it will start to execute.
Executing, it will print methodA and start looking for the next called method (methodB), which is implemented in the B class, then it will print methodB.
The next called method is showName, which is implemented in both classes. Since Java will start looking for the implementation in the same class as the object type, it will find in its first attempt, which is class B.
The main rule is simple: Java will first try to find the method in the object type class (the name that goes after the new operator). If the method is not implemented there, it will start to go up through the super classes.
You have the abstract class A, and it is extended by B. Extends is equivalent to B "is a" A. For example if apple extended fruit, apple 'is a' fruit. It acts like a fruit but also does apple things that a banana wouldn't do. So B acts the same way as A, but then also can do other stuff. So in your example, your B overwrites two methods. They will be called by every B object by default. In order to access A's methods from a B, you need to use the keyword super .
It is part of polymorphism (a key point in java programming) that an object will find any methods in itself first (even if they are overwritten from a parent) and then it will climb the tree of inheritance to find a method that isn't directly in that class.
For your example:
public void methodA() {
System.out.println("methodA"); //This prints no problem.
methodB(); //This searches the "B" class for a method called "methodB" If it can't find it, it checks its parent for a "methodB"
showName();//This searches the "B" class for a method called "showName" If it can't find it, it checks its parent for a "showName"
}
The above code gets called. You know this much (from other comments you made, I'm assuming this.) Once the line methodB() gets called, your object of type B checks the entire B file for the method. It would only jump up to A for the method if it didn't exist. Then it would do the same for showName().

Call method from instance

Let's say I have two classes, A and B, in turn have some methods, something() and nothing() and an instance of B is created in A, as
public class A {
public A() {
B b = new B();
b.nothing();
}
public void something() {
...
}
}
A calling b.nothing() is all standard stuff, but is there any means which by instance b can call a.something(), assuming the instance of A is called a. If not, why is this conceptually wrong?
I don't think there's anything conceptually wrong with this.
However, for the mechanics to work, b needs to know which instance of A to call something() on. For this, either B's constructor, or its nothing() method, needs to take an A reference as an argument.
example 1:
public class B {
public void nothing(A a) {
...
a.something();
...
}
}
example 2:
public class B {
private final A a;
public B(A a) {
this.a = a;
}
public void nothing() {
...
this.a.something();
...
}
}
example 3:
There is a third way, applicable in some circumstances. If B is an inner class of A, it has an implicit reference to its associated instance of A.
public class A {
public void something() { ... }
public class B {
public void nothing() {
...
something();
...
}
}
}
is there any means which by instance b can call a.something()
You can't get hold of the caller in a method so, no, there's no way to do that.
If not, why is this conceptually wrong?
Two issues come to my mind immediately:
What would the type of the caller be? Since anyone could call b.nothing(), you can't assume more than that it's an Object which would result in lots of ugly down casts.
The implementation of b.nothing() shouldn't care about who's calling him. What happens if you refactor A and move the call to b.nothing() to some other class? It would be quite surprising if b.nothing() all of a sudden stopped working.
The only way b.nothing() can call a.something() is if you tell the instance of B about the instance of A. For example:
b.nothing(this);
where B.nothing looks like:
public void nothing(A a)
{
// Do other stuff
a.something();
}
Alternatively, you could pass in this in the constructor to B, which would keep hold of the reference:
B b = new B(this);
b.nothing();
Note that letting this escape during a constructor call is generally a bad idea - you're letting B.nothing() call A.something() on an object which isn't fully initialized yet - its constructor hasn't finished executing. That can lead to undesirable and hard-to-diagnose behaviour sometimes.
To do this, b would require a reference to a. There are two ways to provide that:
Pass such a reference in the constructor of B or give B an appropriate setter.
If B is an inner class of A, then it has such a reference implicitly.

Categories

Resources