Related
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.
Suppose I have class A
public class A
{
public void method()
{
//do stuff
}
}
Also another class B
public class B extends A
{
public void method()
{
//do other stuff
}
}
Now I have the following statements:
A a = new B();
a.method();
Is this an example of run time polymorphism? If yes, then is no binding is done for the reference a at compile time?
The compiler will tell you that this can't work, because there's no relationship between A and B that will allow you to write A a = new B();
B either has to extend A or both have to implement a common interface with void method() in it.
You could have answered this very quickly by trying it with the compiler. Be an experimentalist - it's faster than forums.
UPDATE:
It works, now that B extends A. The binding that you care about, dynamic binding, is done at runtime. The static compile time type for the variable "a" is class A; at runtime it is dynamically bound to a reference of type B. Yes, I would consider this to be an example of polymorphism.
I was waiting to put my answer to another post, into a more correctly classified problem. Your question fits the concept, I've tried to explain in detail. but, since I don't know how link answers, I'll just copy/paste the complete script here .... Kindly go through it, you'll understand everything that there is to understand about your problem, you've asked
let's say compiler has to resolve a call like this : *
A a = new AA(); // Assume AA to be some subclass of class A
a->someFunc(); // and we're invoking a method "someFunc()' on a
*.
Now, compiler will go over following steps methodically.
1.) Firstly, compiler knows the declared type of variable a, so it will check whether the declared type of object a (lets call this, class A for time being), have a method with the name someFunc() and that it must be public. This method could either be declared in class A, or it could be a derived method from one of the base class(es) of class A, but it doesn't matter to compiler and it just checks for it's existence with it's access specifier being public.
Needless to say any error in this step will invite a compiler error.
2.) Secondly, once the method is validated to be a part of the class A, compiler has to resolve the call to the correct method, since many methods could be there with same name (thanks to function overloading). This process of resolving correct method is called overloading resolution. Compiler achieves this by matching the signatures of the called method with all the overloaded methods that are part of the class. So, of all the someFunc() s only the correct someFunc() (matching the signatures with called method) will be found and considered further.
3.) Now comes the difficult part, It may very well happen that someFunc() may have been overridden in one of the subclasses of the class A (lets call this class AA and needless to say it is some subclass of A), and that variable a (declared to be of type A) may actually be referring to an object of class AA, (this is permissible in C++ to enable polymorphism). Now, if the someFunc() method is declared to be of type virtual, in base class (i.e. Class A) and someFunc() has been overriden by subclass(es) of A (either in AA or classes between A and AA), the correct version of someFunc() have to be found out by the compiler.
Now, imagine you're the compiler and you have this task of finding whether the class AA has this method. Obviously, class AA will have this method since, it is a subclass of A and public access of A in class A has already been validated in Step 1 by the compiler !!! . But Alternatively, as mentioned in previous paragraph, someFunc() may be overriden by class AA (or any other class between A and AA), which is what compiler needs to catch. Therefore, you (since, your'e playing the compiler) could do a systematic check to find the bottom-most (lowest in the inheritance tree) overridden method someFunc() starting from class A and ending at class AA. In this search, you'll look for same method signatures as was validated in overloading resolution. This method will be the method which will be invoked.
Now, you may be wondering, "What the heck", is this search done everytime ? ... Well, Not really. The compiler knows the overhead of finding this everytime, and as such, maintains a data-structure called Virtual Table for every class type. Think of virtual table, as mapping from method signatures (which are publicly accessible) to the function pointers. This virtual table is made by compiler during compilation process and is maintained in-memory during program execution. In our example, class A and class AA will both have their own virtual tables. And when compiler has to be find someFunc() in class AA (since actual object pointed by variable a is of type AA), it will simply find the function pointer through the virtual table of Class AA. This is as simple has hashing into the table and is a constant time operation.
Regards
AViD
The code example you've given isn't legal, so I guess the answer is that it's not a kind of polymorphism.
You can't assign a class to a variable of an unrelated type like that. I'm guessing that you might be intending for B to derive from A?
Is this an example of run time polymorphism?
As of the edit: yes that would be runtime polymorphism, since which method is actually executed depends on what is assigned to a.
Edit:
If method() would be static, then calling a.method() would always result in the version of A being called. However, you'd then just write A.method() and if you don't do that any decent IDE would warn you about that (because it might be misleading to call a static method on an instance).
End Edit.
Compile time polymorphism would be the overloading mechanism, i.e. the compiler decides whether to use someMethod(Number) or someMethod(Integer) depending on what it knows about the parameter that is passed (if you pass a Double or just a Number it would be the first one, if you pass an Integer it would be the second).
If yes, then is no binding is done for the reference a at compile time?
What do you mean exactly? Note that the type of a will be A so you can assign everything that extends A at runtime. The compiler will just complain if the assigned value is not an A (you might trick the compiler with a cast, but this is just evil and if this breaks your program, you have been warned ;) )
It should be
public class B extends A {
public void method()
{
//do other stuff
} }
If it were compiling, it would be the B::method() that would be called. (only if you changed your code to make the B class inherit the A class).
In this case your use your object like it was only an A, but if some methods are overidden in B, then these methods are called, instead of A's methods.
class A
{
int i=10;
void show()
{
System.out.println("class A");
}
}
class B extends A
{
int i=5;
public void show()
{
System.out.println("class B");
}
}
class M
{
public static void main(String s[])
{
A a=new B();
a.show();
System.out.println(a.i);
}
}
OUTPUT= class B
10
If class A method is overridden by class B method then why not the variable 'i'?
Because variables are not virtual, only methods are.
It is not overwritten, but hidden. In your output you specifically requested the value of a.i, not ((B)a).i.
This is a "feature" of the implementation. In memory, this looks like so:
a:
pointer to class A
int i
b:
pointer to class B
int i (from A)
int i (from B)
When you access i in an instance of B, Java needs to know which variable you mean. It must allocate both since methods from class A will want to access their own field i while methods from B will want their own i (since you chose to create a new field i in B instead of making A.i visible in B). This means there are two i and the standard visibility rules apply: Whichever is closer will win.
Now you say A a=new B(); and that's a bit tricky because it tells Java "treat the result from the right hand side as if it were an instance of A".
When you call a method, Java follows the pointer to the class (first thing in the object in memory). There, it finds a list of methods. Methods overwrite each other, so when it looks for the method show(), it will find the one defined in B. This makes method access fast: You can simply merge all visible methods in the (internal) method list of class B and each call will mean a single access to that list. You don't need to search all classes upwards for a match.
Field access is similar. Java doesn't like searching. So when you say B b = new B();, b.i is obviously from B. But you said A a = new B() telling Java that you prefer to treat the new instance as something of type A. Java, lazy as it is, looks into A, finds a field i, checks that you can see that field and doesn't even bother to look at the real type of a anymore (because that would a) be slow and b) would effectively prevent you from accessing both i fields by casting).
So in the end, this is because Java optimizes the field and method lookup.
Why no field overrides in Java though?
Well, because instance field lookups in Java happen at compile time: Java simply gives you the value of the field at a given offset in object's memory (based on the type information at hand during compilation: in this case a is declared to be of type A).
void foo() {
A a = new B();
int val = a.i; // compiler uses type A to compute the field offset
}
One may ask "Why didn't compiler use type B since it knows that a is in fact an instance of B? Isn't it obvious from the assignment just above?". Of course, in the case above, it's relatively obvious and compiler may try to be smarter and figure it out.
But that's compiler design "rat hole", what if a "trickier" piece of code is encountered, like so:
void foo(A a) {
int val = a.i;
}
If compiler were "smarter", it would become its job to look at all invocations of foo() and see what real type was used, which is an impossible job since compiler can not predict what other crazy things may be passed to foo() by unknown or yet unwritten callers.
It's a design decision by the developers of Java, and is documented in the Java Language Specification.
A method with the same method signature as a method in its parent class overrides the method in its parent class.
A variable with the same name as a variable in its parent class hides the parent's variable.
The difference is that hidden values can be accessed by casting the variable to its parent type, while overridden methods will always execute the child class's method.
As others have noted, in C++ and C#, to get the same override behavior as Java, the methods need to be declared virtual.
a is an instance of A. You call the constructor B(). But it is still a A class.
That is why i equals 10;
The override from the method will be succeded.
Note a class starts not with
public class A()
but with;
public class A { ... }
Tip: You can use setters and getters to make sure of what data-members you use.
Or: You simply can set the values at the constructor instead of the class declaration.
Because by default the variables are private. You must declare it as "protected", then will be properly inherited.
GIVEN:
class A
{
String s = "A";
}
class B extends A
{
String s = "B";
}
public class C
{
public static void main(String[] args){ new C().go();}
void go()
{
A a = new B();
System.out.println(a.s);
}
}
Question:
What are the mechanics behind JVM when this code is run? How come a.s prints back as "A".
Field references are not subject to polymorphism, so at compile time the compiler is referencing A's field because your local variable is of type A.
In other words, the field behavior is like the Java overloading behavior on methods, not the Java overriding behavior.
You probably expect fields to be overridden like method, with dynamic dispatch based on the runtime type of the object.
That's not how Java works. Fields are not overridden, they are hidden. That means an object of class B has two fields named "s", but which of them is accessed depends on the context.
As for why this is so: it wouldn't really make sense to override fields, since there is no useful way to make it work when the types are different, and simply no point when the type is the same (as you can just use the superclass field). Personally, I think it should simply be a compiler error.
This isn't polymorphism (as tagged).
Java has virtual methods, not virtual member variables - i.e. you don't override a property - you hide it.
Although member variables are inherited from a base class, they are not invoked polymorphically (i.e dynamic invocation does not apply to member variables).
So, a.s will refer to the member in the base class and not the derived class.
Having said that, the code is not following OO principles. The members of a class need to be private/protected (not public or default) depending on the business use case and you need to provide public methods to get and set the values of the member.
I have something unclear concerning casting reference variable in Java.
I have two classes A and B. A is the super class of B.
If I have the two objects, and then the print statement:
A a = new A(); //superclass
B b = new B(); //subclass
System.out.println ((A)b);
then what exactly is happening when the println method is executed?
I know that because B is a subclass of A, I am allowed to make the following cast:
A a2 = (A)b;
I also know that when println takes a reference variable as argument, then the toString() method of the class, which has created the object-argument, is invoked (implicitly). This is so, because the method println() is looking for an argument of type String, and the toString() method represent the object as a string. And even if we don't write toString(), the method is invoked - implicitly. So, the following two statements are equivalent:
System.out.println (b);
System.out.println (b.toString());
So, my question is: what is the implicit action taken when we have
System.out.println ((A)b);
?
I suppose that the type of the reference variable b is automatically changed from B to A. The variable should still be pointing to the same object - the one created with
B b = new B();
but just the type of b would be now changed. Is this correct?
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
Thanks a lot.
Regards
The cast has no impact in this case.
The System.out.println(XXX) takes parameters of different types (multiple overloaded versions) but in this case you would get the version that takes Object. Since every object in Java supports toString(), toString is invoked on the actual argument, no matter what it is.
Now, since all methods in Java are dispatched dynamically, the version that runs is the version that corresponds to the dynamic type. Casting an object of B to A only changes the static (declared) type of the expression. The dynamic type (what's really in there) is still a B. Therefore, the version in B gets invoked.
There are many declarations of println(...) in the PrintStream class (which is the type of System.out).
Two of them are:
void println(String x)
void println(Object x)
When you call println((A)b) the compiler chooses to call println(Object) because A is not String (or any of the other types that println supports). When you call println(b.toString()), the compiler chooses println(String) because you are passing a String.
In your case, casting b to A has no effect since println() doesn't have a declaration for either A or B types. But the cast will still occur (because you asked for it), or maybe it won't because the compiler optimises it away as it knows it is redundant and it can't fail and has no effect.
It is not idiomatic to write:
A a2 = (A)b;
as this is redundant since B is a subclass of A. It may be that the compiler will optimise away the cast (which is a run-time operation to check whether an object is of a particular type, never to change it's type).
Once an object of type B is constructed, it's type never changes. It is always a B:
class B extends/implements A {...}
B b = new B(); // construct a B
A a = b; // assign a B to an A variable, it's superclass
A a = (A) b // as above including check to see that b is an A (redundant, may be optimised away).
B b = a; // Syntax error, won't compile
B b = (B) a // Will check whether a is of type B then assign to variable b
In the last case, since B is a subclass of A, it may be that a holds an instance of B and the cast will succeed. Or it may be that a holds an instance of some other class that extends/implements/is A and isn't a B and you'll get a ClassCastException.
So since an object of type B always retains it's identity (it's "B"-ness) then any (instance-) methods called on that object will always call B's implementation regardless of whether the variable through which you access the object was declared as A or B.
Remember, you can only call methods that are declared in the class that the variable is defined as.
So for example, if B declares a method b_only() then the compiler won't allow you to write a.b_only(); you could write ((B)a).b_only() though.
Since Java methods all have dynamic dispatch, which function gets called doesn't depend on the static type of the reference. Therefore, the results will be the same with or without the cast. [The results could be different if you were downcasting - the casting version could throw an exception]
Is this correct?
Sort of. The result of the casting expression would be of the A type. The type of the 'b' variable will always remain of type B.
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
The instance methods of the underlying object will be called. Example:
class Foo {
public static void main(String[] args) {
B b = new B();
assert "B".equals(((A) b).m());
}
}
class A {
String m() { return "A"; }
}
class B extends A {
String m() { return "B"; }
}
Always think of your object as the type it's instantiated as (B in your case). If it's upcast to A think of it as--hmm--think of it as B putting on A clothes. It may look like an A, and you may not be able to do any of the nice B things you want to do, but inside the clothes it's still a B--the clothes don't change the underlying object at all.
So the summary would be--you can only call the methods in A, but when you call it, it goes straight through and executes it as it would if it was a B.
I think when we use reference variable in java and by using this variable we can assign a object of any class type. most of the cases we create a reference variable of Interface and abstract class because we can't create the object of interface and abstract class so assign the object of class in reference variable of Interface or abstract class.
Ex-
Interface X {
public abstract void xx();
public abstract void yy();
}
Class XXX implements X {
...........
}
Class XY extends XXX {
X xy = new XXX();
}
here xy is a reference of Interface X and assign the object of Class XXX in the reference of Interface.
so according to my point of view by using reference variable we can also use interface to participate in Object creation.
The casting, as has been mentioned, is irrelevant in this case due to overridden methods being dynamically bound. Since the toString is present in all objects it meets this condition and thus the object type and method to call are determined at runtime.
Please note though, this is NOT the case with all methods since only overridden methods are dynamically bound. Overloaded methods are statically bound. Many of the answers here mention that java methods are always dynamically bound, which is incorrect.
See this question for a more detailed explanation.
question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
in this case the method of subclass b is called ; to convincingly understand why; you may relate to the following real world scenario
consider a parent class Father exhibiting a behaviour(method): height
defined as
the father is tall ;height = 6'2"
Son is a child class inheriting the height behavior from Father ;as a result he is also tall; height being 6' clearly overriding the behaviour
whenever your subclass Son calls the behavior height on his name he displays the overridden behavior i.e his own height 6' .