public class Super {
public void methodA() {
System.out.println("super A");
}
public void methodC(Super arg) {
System.out.println("C1");
}
public void methodC(Sub arg) {
System.out.println("C2");
}
} // end class Super
public class Sub extends Super {
public void methodA() {
System.out.println("sub A");
}
public void methodC(Super arg) {
System.out.println("C3");
}
public void methodC(Sub arg) {
System.out.println("C4");
}
} // end class Sub
public class BindingQuestion {
public static void main (String[] args){
Super one = new Super();
Super two = new Sub();
Sub three = new Sub();
two.methodC(three)
}
}
I'm confused as to why two.method(C) returns C4. Isn't two declared as type Super. Shouldn't this mean that it accesses only the Super methods? I thought it would return C2. At least this is what I infered from an answer given to me by #stvcisco in a similar previous question. Dynamic Binding Java. Does an object have the methods of its declared type, or its actual type?
Am I misinterpreting his answer?
The instance method being called depends on the runtime type of the instance.
In Super two = new Sub();, the run time type is Sub (even though the compile time type is Super). Therefore two.methodC(three) calls Sub's methodC(Sub arg).
The compile time type determines the available method signatures that the compiler would accept. Since Super contains a method whose signature matches the call two.methodC(three), this code can pass compilation. However, the actual method that gets invoked is only determines at run time, based on the run time type of two.
Isn't two declared as type Super.
Yes it is.
Shouldn't this mean that it accesses only the Super methods?
No it does not mean this.
What happens is as follows:
At compilation time, the compiler checks if there is a method in Super which can handle methocC(Sub). There are actually two of them. methodC(Super) and methodC(Sub). The compiler selects the most specific signature to be bound at runtime. This one is the methodC(Sub), because Sub is a subclass of Super.
At runtime, the VM looks up for methodC(Sub) in the most specific class possible. This one is Sub, since there is a method defined there with the signature methodC(Sub), therefore this one is bound.
This is because you overwrite the two functions methodC(Super),methodC(Sub).And Super two = new Sub(),this is called polymorphism.It means it would point to the local variable "new Sub()" and the functions in Class Sub though you name it Class Super.And all about this is completing automatically.If you hava a method methodC(Super),methodC(Sub) in Class Super ,yet methodB(Super),methodB(Sub) in Class Sub.The same operation 'Super two = new Sub();two.methodC(Three);will return "C2".In addition, the question you ask is quite common.You need to write more code to understand it.It would be better to write a project with more classes.LikeClass Super;Class Sub1 extends Super;Class Sub2;...,Of course,you can also useInterface`!
Case 1) 'two' is a type of Super class but it contain sub class object. So when you call some method which is defined in both super and sub class then it call the sub class method because sub class has override that method. If it does not found those method in sub class then it call to the super class method.
Case 2) When you remove both of the method ' methodC(Sub arg)' from super and sub class then it call the sub class method 'methodC(Super arg)', if it does not found then it call super class method.
When a sub class object is assigned to super class object then it will
call first sub class method because sub class override super class
method.
What I think is most important while understanding the concept of Dynamic and Static Binding is that many times we think both types of bindings cannot take place within the scope of a program - that both these two are mutually exclusive This is not true. Its just that the two happen at different stages of the program execution and throw an error that time if any ambiguity is found. For example, in your case:
public class BindingQuestion {
public static void main (String[] args){
Super one = new Super();
Super two = new Sub();
Sub three = new Sub();
two.methodC(three)
}
}
During compile time ----------------
When the program is being compiled, the java compiler will traverse through each and every executable code. When it comes to
two.methodC(three)
it will first check if methodC(three) with this signature is available in the class of the type SUPER. Why Super? Because objects in java are accessed through reference. When you do this:
Super two = new Sub();
This means, for the reference two of type Super, you are pointing to an object of SUB. Which is fine. Why? Because in java, a subclasses always have a few extra properties besides the ones implanted into it by its superclass. So from the piece of code above all the properties of SUB which are common with two will work just fine - they will be easily accessed by the reference variable of SUPER type.
So, the compiler checks if the method
After the compiler has executed through the program and not found any ambiguity in terms of the type of the reference matching with the methodC(three) is present in the SUPER class or not.
According to the structure of inheritance that you have provided, is there a method called methodC is the SUPER class. Answer is yes! It does exists. Now, do the arguments match? In other words does the signature match? The answer is yes. Because in SUPER the signature expected in public void methodC(Sub arg). And guess what? Three, is of type SUB. So compiler will pass this line without creating any errors.
Coming to Run time
You must remember that Objects and invoked only and only at runtime. Check of types of methods and signatures is done during compile time.
Now, Java Runtime instance, while invoking the object two, realizes that actually the object two is of SUB class and invokes the method in the SUB class.
Hope this helped.
Related
Consider the multilevel inheritance hierarchy in Java:
public class First {public String name() { return "First"; }}
public class Second extends First {
public void m1() {
System.out.print(super.name() + " rules");
System.out.prinln(" but " + name() + " is even better.");
}
public String name() { return "Second"; }}
public class Third extends Second {public String name() { return "Third"; }}
The Third class doesn't override the m1 method- it just inherits it. So if you run the following code:
Third varThird = new Third();
varThird.m1();
You get:
First rules but Third is even better.
This seems to violate the rule that at runtime, the actual type of the object is used to determine which implementation of the method is run. The method from the Second class appears to be the method that is run. How do you reconcile rules from Java inheritance (public methods are inherited by subclasses) with rules from polymorphism (at runtime, Java uses an object's actual type to determine which version of the method is implemented). Do methods that are not overridden in the subclass actually get "inherited"?
Ok, I think I undenstand the question now. You are confused about why super is rot resolved at runtime.
The reason is simple. Java only use the exact type to determine which method to call, for virtual methods. But constructors are not virtual, so a call to a constructor is always determined at compile time.
The search starts at the subtype for the method. Then the JVM successively goes further up the inheritance hierarchy to find the specific method.
It is called dynamic binding if I remember correctly.
Edit
Okay you are wondering why you get Third is even better. when m1() is only defined in Second. You are expecting the output Second is even better.
The method is inherited vom Subtyp Second as the JVM uses this method in the inheritance hierarchy as Third does not override this method.
In second you refer to
super().name where super() refers to the parent which in this case is First and therefore you get First rules but
Then you are invoking name() method which is defined in Third and therefore returning the name defined in Third
Can anyone provide a simple example that explains the difference between Dynamic and Static polymorphism in Java?
Polymorphism
1. Static binding/Compile-Time binding/Early binding/Method overloading.(in same class)
2. Dynamic binding/Run-Time binding/Late binding/Method overriding.(in different classes)
overloading example:
class Calculation {
void sum(int a,int b){System.out.println(a+b);}
void sum(int a,int b,int c){System.out.println(a+b+c);}
public static void main(String args[]) {
Calculation obj=new Calculation();
obj.sum(10,10,10); // 30
obj.sum(20,20); //40
}
}
overriding example:
class Animal {
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();//output: Animals can move
b.move();//output:Dogs can walk and run
}
}
Method overloading would be an example of static polymorphism
whereas overriding would be an example of dynamic polymorphism.
Because, in case of overloading, at compile time the compiler knows which method to link to the call. However, it is determined at runtime for dynamic polymorphism
Dynamic (run time) polymorphism is the polymorphism existed at run-time. Here, Java compiler does not understand which method is called at compilation time. Only JVM decides which method is called at run-time. Method overloading and method overriding using instance methods are the examples for dynamic polymorphism.
For example,
Consider an application that serializes and de-serializes different
types of documents.
We can have ‘Document’ as the base class and different document type
classes deriving from it. E.g. XMLDocument , WordDocument , etc.
Document class will define ‘ Serialize() ’ and ‘ De-serialize() ’
methods as virtual and each derived class will implement these
methods in its own way based on the actual contents of the documents.
When different types of documents need to be
serialized/de-serialized, the document objects will be referred by
the ‘ Document’ class reference (or pointer) and when the ‘
Serialize() ’ or ‘ De-serialize() ’ method are called on it,
appropriate versions of the virtual methods are called.
Static (compile time) polymorphism is the polymorphism exhibited at compile time. Here, Java compiler knows which method is called. Method overloading and method overriding using static methods; method overriding using private or final methods are examples for static polymorphism
For example,
An employee object may have two print() methods one taking no
arguments and one taking a prefix string to be displayed along with
the employee data.
Given these interfaces, when the print() method is called without any
arguments, the compiler, looking at the function arguments knows which function is meant to be called and it generates the object code
accordingly.
For more details please read "What is Polymorphism" (Google it).
Binding refers to the link between method call and method definition.
This picture clearly shows what is binding.
In this picture, “a1.methodOne()” call is binding to corresponding methodOne() definition and “a1.methodTwo()” call is binding to corresponding methodTwo() definition.
For every method call there should be proper method definition. This is a rule in java. If compiler does not see the proper method definition for every method call, it throws error.
Now, come to static binding and dynamic binding in java.
Static Binding In Java :
Static binding is a binding which happens during compilation. It is
also called early binding because binding happens before a program
actually runs
.
Static binding can be demonstrated like in the below picture.
In this picture, ‘a1’ is a reference variable of type Class A pointing to object of class A. ‘a2’ is also reference variable of type class A but pointing to object of Class B.
During compilation, while binding, compiler does not check the type of object to which a particular reference variable is pointing. It just checks the type of reference variable through which a method is called and checks whether there exist a method definition for it in that type.
For example, for “a1.method()” method call in the above picture, compiler checks whether there exist method definition for method() in Class A. Because ‘a1′ is Class A type. Similarly, for “a2.method()” method call, it checks whether there exist method definition for method() in Class A. Because ‘a2′ is also Class A type. It does not check to which object, ‘a1’ and ‘a2’ are pointing. This type of binding is called static binding.
Dynamic Binding In Java :
Dynamic binding is a binding which happens during run time. It is also
called late binding because binding happens when program actually is
running.
During run time actual objects are used for binding. For example, for “a1.method()” call in the above picture, method() of actual object to which ‘a1’ is pointing will be called. For “a2.method()” call, method() of actual object to which ‘a2’ is pointing will be called. This type of binding is called dynamic binding.
The dynamic binding of above example can be demonstrated like below.
Reference static-binding-and-dynamic-binding-in-java
method overloading is an example of compile time/static polymorphism because method binding between method call and method definition happens at compile time and it depends on the reference of the class (reference created at compile time and goes to stack).
method overriding is an example of run time/dynamic polymorphism because method binding between method call and method definition happens at run time and it depends on the object of the class (object created at runtime and goes to the heap).
In simple terms :
Static polymorphism : Same method name is overloaded with different type or number of parameters in same class (different signature). Targeted method call is resolved at compile time.
Dynamic polymorphism: Same method is overridden with same signature in different classes. Type of object on which method is being invoked is not known at compile time but will be decided at run time.
Generally overloading won't be considered as polymorphism.
From java tutorial page :
Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class
Method Overloading is known as Static Polymorphism and also Known as Compile Time Polymorphism or Static Binding because overloaded method calls get resolved at compile time by the compiler on the basis of the argument list and the reference on which we are calling the method.
And Method Overriding is known as Dynamic Polymorphism or simple Polymorphism or Runtime Method Dispatch or Dynamic Binding because overridden method call get resolved at runtime.
In order to understand why this is so let's take an example of Mammal and Human class
class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
class Human extends Mammal {
#Override
public void speak() { System.out.println("Hello"); }
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
}
I have included output as well as bytecode of in below lines of code
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
And by looking at above code we can see that the bytecodes of humanMammal.speak() , human.speak() and human.speak("Hindi") are totally different because the compiler is able to differentiate between them based on the argument list and class reference. And this is why Method Overloading is known as Static Polymorphism.
But bytecode for anyMammal.speak() and humanMammal.speak() is same because according to compiler both methods are called on Mammal reference but the output for both method calls is different because at runtime JVM knows what object a reference is holding and JVM calls the method on the object and this is why Method Overriding is known as Dynamic Polymorphism.
So from above code and bytecode, it is clear that during compilation phase calling method is considered from the reference type. But at execution time method will be called from the object which the reference is holding.
If you want to know more about this you can read more on How Does JVM Handle Method Overloading and Overriding Internally.
Polymorphism:
Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.
Dynamic Binding/Runtime Polymorphism :
Run time Polymorphism also known as method overriding. In this Mechanism by which a call to an overridden function is resolved at a Run-Time.
public class DynamicBindingTest {
public static void main(String args[]) {
Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
vehicle.start(); //Car's start called because start() is overridden method
}
}
class Vehicle {
public void start() {
System.out.println("Inside start method of Vehicle");
}
}
class Car extends Vehicle {
#Override
public void start() {
System.out.println("Inside start method of Car");
}
}
Output:
Inside start method of Car
Static Binding /compile-time polymorphism:
Which method is to be called is decided at compile-time only.
public class StaticBindingTest {
public static void main(String args[]) {
Collection c = new HashSet();
StaticBindingTest et = new StaticBindingTest();
et.sort(c);
}
//overloaded method takes Collection argument
public Collection sort(Collection c){
System.out.println("Inside Collection sort method");
return c;
}
//another overloaded method which takes HashSet argument which is sub class
public Collection sort(HashSet hs){
System.out.println("Inside HashSet sort method");
return hs;
}
}
Output:
Inside Collection sort metho
Static Polymorphism: is where the decision to resolve which method to accomplish, is determined during the compile time. Method Overloading could be an example of this.
Dynamic Polymorphism: is where the decision to choose which method to execute, is set during the run-time. Method Overriding could be an example of this.
Polymorphism refers to the ability of an object to behave differently for the same trigger.
Static polymorphism (Compile-time Polymorphism)
Static Polymorphism decides which method to execute during compile
time.
Method Overloading is an example of static polymorphism, and it is
requred to happens static polymorphism.
Static Polymorphism achieved through static binding.
Static Polymorphism happens in the same class.
Object assignment is not required for static polymorphism.
Inheritance not involved for static polymorphism.
Dynamic Polymorphism (Runtime Polymorphism)
Dynamic Polymorphism decides which method to execute in runtime.
Method Overriding is an example of dynamic polymorphism, and it is
requred to happens dynamic polymorphism.
Dynamic Polymorphism achieved through dynamic binding.
Dynamic Polymorphism happens between different classes.
It is required where a subclass object is assigned to super class
object for dynamic polymorphism.
Inheritance involved for dynamic polymorphism.
Compile time polymorphism(Static Binding/Early Binding): In static polymorphism, if we call a method in our code then which definition of that method is to be called actually is resolved at compile time only.
(or)
At compile time, Java knows which method to invoke by checking the method signatures. So, this is called compile-time polymorphism or static binding.
Dynamic Polymorphism(Late Binding/ Runtime Polymorphism): At run time, Java waits until runtime to determine which object is actually being pointed to by the reference. Method resolution was taken at runtime, due to that we call as run time polymorphism.
Consider the code below:
public class X
{
public void methodA() // Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() // Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
//this takes input from the user during runtime
System.out.println("Enter x or y");
Scanner scanner = new Scanner(System.in);
String value= scanner.nextLine();
X obj1 = null;
if(value.equals("x"))
obj1 = new X(); // Reference and object X
else if(value.equals("y"))
obj2 = new Y(); // X reference but Y object
else
System.out.println("Invalid param value");
obj1.methodA();
}
}
Now, looking at the code you can never tell which implementation of methodA() will be executed, Because it depends on what value the user gives during runtime. So, it is only decided during the runtime as to which method will be called. Hence, Runtime polymorphism.
Method overloading is a compile time polymorphism, let's take an example to understand the concept.
class Person //person.java file
{
public static void main ( String[] args )
{
Eat e = new Eat();
e.eat(noodle); //line 6
}
void eat (Noodles n) //Noodles is a object line 8
{
}
void eat ( Pizza p) //Pizza is a object
{
}
}
In this example, Person has a eat method which represents that he can either eat Pizza or Noodles. That the method eat is overloaded when we compile this Person.java the compiler resolves the method call " e.eat(noodles) [which is at line 6] with the method definition specified in line 8 that is it method which takes noodles as parameter and the entire process is done by Compiler so it is Compile time Polymorphism.
The process of replacement of the method call with method definition is called as binding, in this case, it is done by the compiler so it is called as early binding.
Following on from Naresh's answer, dynamic polymorphism is only 'dynamic' in Java because of the presence of the virtual machine and its ability to interpret the code at run time rather than the code running natively.
In C++ it must be resolved at compile time if it is being compiled to a native binary using gcc, obviously; however, the runtime jump and thunk in the virtual table is still referred to as a 'lookup' or 'dynamic'. If C inherits B, and you declare B* b = new C(); b->method1();, b will be resolved by the compiler to point to a B object inside C (for a simple class inherits a class situation, the B object inside C and C will start at the same memory address so nothing is required to be done; it will be pointing at the vptr that they both use). If C inherits B and A, the virtual function table of the A object inside C entry for method1 will have a thunk which will offset the pointer to the start of the encapsulating C object and then pass it to the real A::method1() in the text segment which C has overridden. For C* c = new C(); c->method1(), c will be pointing to the outer C object already and the pointer will be passed to C::method1() in the text segment. Refer to: http://www.programmersought.com/article/2572545946/
In java, for B b = new C(); b.method1();, the virtual machine is able to dynamically check the type of the object paired with b and can pass the correct pointer and call the correct method. The extra step of the virtual machine eliminates the need for virtual function tables or the type being resolved at compile time, even when it could be known at compile time. It's just a different way of doing it which makes sense when a virtual machine is involved and code is only compiled to bytecode.
From what I understand about dynamic binding, the JVM, at runtime, looks at the actual type of an object and searches for an implementation in that class and works its way up through the inheritance levels.
For example if we have: Vehicle v = new Car();
Assuming that the class Car extends Vehicle, we can see that the reference variable type is Vehicle and the object type is Car.
If we were to say: v.start():
The JVM would look for the start method implementation first in the Car class and then in the Vehicle class.
An example of this is in this code:
public class scratch{
public static void main(String [] args){
Vehicle v = new Car();
v.start();
}
}
class Vehicle{
public void start(){
System.out.println("Vehicle class");
}
}
class Car extends Vehicle{
public void start(){
System.out.println("Car class");
}
}
The output of this code, as expected is: "Car class"
This is my question: If I take out the start method from class Vehicle, completely erase it, the program won't run anymore. From what I understand about dynamic binding, the JVM should still look at the actual type of the object (which in this case is Car) and still run the car implementation of the start method. However, it does not do this.
Why?
The problem with removing start() from Vehicle has to do with polymorphism. In Vehicle, if you define start() here, then that is what says that all Vehicles, even subclasses, have that method.
If you remove start() from Vehicle(), then it can't be guaranteed that any Vehicle has a start() method, even though we know it's a Car that does have start(). What if there is a HorselessCarriage class that extends Vehicle but doesn't define start()? Then, there is no start() method. For that reason, if there's no start() method on Vehicle, you can't call start() on a Vehicle variable.
The whole point of being able to call start() on a Vehicle is to ensure that any Vehicle implementation has a start() method to call.
UPDATE
The JVM takes the runtime type of the object and looks for a method matching the signature of the method call. If not found, it walks up the inheritance tree to the superclass and looks for the method there.
More details are given in the JLS, Section 15.12.4.4:
Let X be the compile-time type of the target reference of the method
invocation. Then:
If class S contains a declaration for a non-abstract method named m
with the same descriptor (same number of parameters, the same
parameter types, and the same return type) required by the method
invocation as determined at compile time (§15.12.3), then:
If the invocation mode is super or interface, then this is the method
to be invoked, and the procedure terminates.
If the invocation mode is virtual, and the declaration in S overrides
(§8.4.8.1) X.m, then the method declared in S is the method to be
invoked, and the procedure terminates.
If the invocation mode is virtual, and the declaration in S does not
override X.m, and moreover X.m is declared abstract, then an
AbstractMethodError is thrown.
Otherwise, if S has a superclass, this same lookup procedure is
performed recursively using the direct superclass of S in place of S;
the method to be invoked is the result of the recursive invocation of
this lookup procedure.
Here, S appears to be the runtime type of the object.
In nutshell, JVM need one endpoint to begin the search for the reference of the start method, not matter the object type have a method that you want to invoke, JVM need a mirror to ensure you are trying to call an existing method.
When you have the start() method in the Vehicle class, Car is Overriding that method. When you remove the start() method from Vehicle, you are no longer overriding that method. So calling v.start() has no method to call. This is why you should use #Override, so that it is clear in the code what is happening. In order to call start() on Car in the case where there is no start() method in Vehicle, you'd first have to cast the vehicle to the Car class.
But once you remove the method, Vehicle no longer has any "start" functionality: it is an unknown method in the Vehicle class, and you are accessing it through a Vehicle reference. To make java do what you want, you could do
abstract class Vehicle
{
public abstract void start();
}
Your code should then work again, because all children of Vehicle are now guaranteed a start method. But as it stands in your example, once the start method is removed, there's no guarantee that some previous statement hasn't created some other Vehicle descendant, e.g., Motorcycle without a start method and assigned it to your v reference.
I think a simple way to see the problem is to introduce a method. Here's how the method is defined:
public void callStart(Vehicle vehicle) {
vehicle.start();
}
This method lets you pass in a concrete Car or a concrete Vehicle.
Lets pretend that Java lets you compile this code. If Java let you do this for a Vehicle without a start() method, then you'd have to discover the error at runtime. But Java saves you some time by letting you know when you've compile that you have an error.
This is different from some dynamic languages like Javascript. If this were JavaScript you could pass in a concrete Vehicle and then you'd have to discover your error at runtime. Another difference is that in JavaScript, you could pass in a concrete Car and it would work without error. This is called duck typing and is a feature Java doesn't have.
I've studied that in case of instance methods, at run time the jvm uses the actual class of instance and in case of class methods the compiler will only look at the declared type of a reference variable not the actual class..
I studied this concept instance method hiding..
And in my proram I've used interface reference variable to store the object of the class and try to access the instance method of the class using this but it raise an error..
My program is as follows:
interface A
{
void show();
}
class B implements A
{
public void show()
{
System.out.println("Interface Method");
}
void info()
{
System.out.println("IN Info");
}
}
class interDemo
{
public static void main(String args[])
{
A a;
B b=new B();
a=b;
a.show();
a.info();
}
}
Please help me to understand the conept...
The compiler is telling you that the type A does not have a method called info defined. This is true: the compiler doesn't know that at runtime, the type of a will actually be B, which does have the info method. It would be unsafe to allow the a.info() call to actually be compiled and emitted into bytecodes, there's nothing to say that a will always be of type B.
This is known as static typing. In Java and other static-typed languages, you need to "cast" a variable in order to force the compiler to treat it as another type. In this case, you can write ((B) a).info().
sjr is correct. Here's another way to look at it:
You're specifying that a A can only show. That means when you have a A reference variable, that's all you can do.
That means any class that is willing to show can implement that interface. Clients that need an object to show can use an A without knowing or caring whether that the underlying class has other methods. This is a key aspect of the abstraction provided by object-oriented programming.
You might probably want to see this lecture on YouTube. It covers you problem and I hope it will help you.
In short: static type of a is A. After assigning b to a, dynamic type of a is B. So at this point, static type a is A and dynamic type of a is B. Compiler does not follow dynamic types, it only checks static types. So it will not let do anything other then static type will allow.
So in your example if you are using reference of static type A, you can only call methods from class A.
super concept without confusion
=====================================
2 rules to know from where a method will execute(when super type reference is used to call methods)
NOTE:check "object creation"/"reference assignment" statement for applying rule
1 RULE: 1st check the method to be called.If static/overloaded/single--then it becomes static polymorphism/static(compiler looks for reference type)---hence always execute from reference type
2 RULE: check method to be called --if overridden--then it becomes dynamic polymorphism(jvm looks for object type)---hence always executed from object type(i.e right to new keyword)
for example:
super s=new child();
s.play();
here 2 cases:
1st: check play() is what i.e static(static/overloaded/single method) or dynamic(overridden)
2nd: if static it will execute from super i.e reference type leads to compile time polymorphism
if dynamic it will execute from child i.e object type leads to dynamic polymorphism
How is method overriding implemented in Java? In C++ we have the concept of vtable.. how is this implemented internally in Java?
To answer the question, which is specifically how overriding is implemented in the virtual machine, there's a write up available in Programming for the Java Virtual Machine (Google Books link).
The VM will look for an appropriate method definition in the referenced class, and then work its way up through the inheritance stack. Obviously at some stage various optimisations will apply.
See here for a description of the relevant bytecode instruction invokevirtual:
invokevirtual looks at the descriptor
given in , and determines
how many arguments the method takes
(this may be zero). It pops these
arguments off the operand stack. Next
it pops objectref off the stack.
objectref is a reference to the object
whose method is being called.
invokevirtual retrieves the Java class
for objectref, and searches the list
of methods defined by that class and
then its superclasses, looking for a
method called methodname, whose
descriptor is descriptor.
As gustafc has highlighted below, various optimisations can apply, and no doubt the JIT will introduce further.
Method overriding in Java is a concept based on polymorphism OOPS
concept which allows programmer to create two methods with same name
and method signature on interface and its various implementation and
actual method is called at runtime depending upon type of object at
runtime. Method overriding allows you to write flexible and extensible
code in Java because you can introduce new functionality with minimal
code change.
There are few rules which needs to be followed while overriding any method in Java, failure to follow these rules result in compile time error in Java.
First and most important rule regarding method overriding in Java is that you can only override method in sub class. You can not override method in same class.
Second important rule of method overriding in Java that name and signature of method must be same in Super class and Sub class or in interface and its implementation.
Third rule to override method in Java is that overriding method can not reduce accessibility of overridden method in Java. For example if overridden method is public than overriding method can not be protected, private or package-private; But opposite is true overriding method can increase accessibility of method in Java, i.e. if overridden method is protected than overriding method can be protected or public.
Another worth noting rule of method overriding in Java is that overriding method can not throw checked Exception which is higher in hierarchy than overridden method. Which means if overridden method throws IOException than overriding method can not throw java.lang.Exception in its throws clause because java.lang.Exception comes higher than IOException in Exception hierarchy. This rule doesn't apply to RuntimeException in Java, which is not even need to be declared in throws clause in Java.
You can not override private, static and final method in Java. private and static method are bonded during compile time using static binding in Java and doesn't resolve during runtime. overriding final method in Java is compile time error. Though private and static method can be hidden if you declare another method with same and signature in sub class.
Overridden method is called using dynamic binding in Java at runtime based upon type of Object.
If you are extending abstract class or implementing interface than you need to override all abstract method unless your class is not abstract. abstract method can only be used by using method overriding.
Always use #Override annotation while overriding method in Java. Though this is not rule but its one of the best Java coding practice to follow. From Java 6 you can use #Override annotation on method inherited from interface as well.
--Defining the same method with the same method signature(i.e. same number/type of arguments and same return type/s.)in base and derived class.
--Which method is to be called is decided at runtime so, it is also called runtime polymorphism/late binding.
--we should override the method defined in the superclass.
--when the method is called the method defined in the subclass is called and executed instead of the one in superclass.
--we overcome this by use of 'super' keyword.
//program
class A
{
void disp(){
System.out.println("class A");
}
}
class B extends A
{
public void disp(){
System.out.println("class B");
}
}
public class ExampleIdea{
public static void main(String[] args){
A a = new B(); //Parent reference but B class object (we can achieve polymorphism when parent class reference is used to refer a child class object)
B b = new B(); //B class reference and B class object
A c = new A();
a.disp(); //runs the method in B class
b.disp(); //runs the method in B class
c.disp(); //runs then method in A class
}
}//end of program
when we run this output will be class B.
In order to access the function of class A we have to use super keyword
as:
class B extends A
{
public void disp(){
System.out.println("class B");
super.disp();
}
Maybe this comparison of C++ Vtables and Java method invocation tables is of interest.
Method overriding
It means one method is available in supper class which is displaying some string, but you want to extend this class, and also you want to print your own method at that time you need to overriding this method into your local class.
This is a basic introduction to the method overriding.
Example:
class Animal
{
public void displayMessage()
{
System.out.println("Animal is eating");
}
}
class Dog extends Animal
{
public void displayMessage()
{
System.out.println("Dog is eating");
}
public static void main(String arg[])
{
Dog d=new Dog();
d.displayMessage();
}
}
OUTPUT:
Dog is eating
Advantages of Method Overriding is that the class ca give its own specific implementation to an inherited method without any modifying the parent class method.
The rules of Method overriding are:
The argument list : the argument list must be the same.
Access Modifier : if you're overriding the method you must give the same modifier of super class method suppose super class have the public method you cannot give the protected or private vice versa.
As long as the function (method) you wish to override is not marked as final you just simply override the method by extending the class which holds that method and then provide a method with same signature but different body.