Hi ce_neha, A good problem caught.
See , in first case you are not actually doing downcasting. It is a part of primitive casting, often called as "narrowing". So it is bit different from that of second case.
Downcasting is called in the case of narrowing down an object of "Super class" to the object of its "sub class".
Now coming to main problem why you are getting runtime exception [Which I am guessing is "ClassCastException" right? ]
go2((Redwood) new Tree(),new Redwood());//------------------->downcasting
In the above line, you are creating a "Superclass" object and downcasting it to "Sub class" . Same thing you are doing in following line also
Redwood r2=(Redwood)t1;
Now compiler feels that downcasting is fine as I am casting to an object in the inheritance tree only. So your second program compiles fine but it is not sure whether at run time, your program is in actual receiving the object of "Sub class" type or not.
Let me explain the thing with a simple example . My below program will also give Runtime Exception, even though it is simple straightforward downcast.
/**
*
* @author sookie
*/
public class Redwood extends Tree
{
public static void main(String[] args){
Tree t= new Tree();
Redwood r = (Redwood) t;
}
}
class Tree{}
Above program compiles fine but throws "ClasscastException" at runtime because it never guarantees that at runtime object passed is of type "Redwood" or not.
So in order to avoid such exceptions "instanceof" comes for the rescue. It gives the guarantee that the object passed is of desired type. So , if in my above simple program only, I add a check using "instanceof", I will not get any Runtime Exception.
/**
*
* @author sookie
*/
public class Redwood extends Tree
{
public static void main(String[] args){
Tree t= new Tree();
if(t instanceof Redwood){
Redwood r = (Redwood) t;
}
}
}
class Tree{}
Hope you got the point and the same thing I have changed in your original second case program also 😀
public class Redwood extends Tree
{
public static void main(String s[])
{
new Redwood().go();
}
void go()
{
go2(new Tree(),new Redwood());
go2(new Tree(),new Redwood());//------------------->downcasting
}
void go2(Tree t1,Redwood r1)
{
if(t1 instanceof Redwood){
Redwood r2=(Redwood)t1;
}
Tree t2=(Tree)r1;
}
}
class Tree{}
Bottom Line: Avoid downcasting without making a check using "
instanceof" keyword. It gives guarantee of the object being passed at the runtime while casting.