Type casting in Java is to cast one type, a class or interface, into another type i.e. another class or interface. Since Java is an Object-oriented programming language and supports both Inheritance and Polymorphism, It’s easy that Super class reference variable is pointing to SubClass objects but the catch here is that there is no way for Java compiler to know that a Superclass variable is pointing to SubClass object. This means you can not call a method that is declared in the subclass. In order to do that, you first need to cast the Object back into its original type. This is called type casting in Java. You can type cast both primitive and reference type in Java. The concept of casting will be clearer when you will see an example of type casting in the next section.
Type casting also comes with the risk of ClassCastException in Java, which is quite common with a method that accepts Object type and later types cast into more specific types.
We will see when ClassCastException comes during type casting and How to avoid it in the coming section of this article. Another worth noting point here is that from Java 5 onwards you can use Generics to write type-safe code to reduce the amount of type casting in Java which also reduces the risk of java.lang.ClassCastException at runtime.
What is Type Casting in Java? Up Casting and Down Cast
From the first paragraph, we pretty much know What is type casting in Java. Anyway, In simple words, type casting is a process of converting one type, which could be a class or interface to another, But as per rules of Java programming language, only classes or interfaces (collectively known as Type) from the same type hierarchy can be cast or converted into each other.
If you try to cast two objects which don't share same type hierarchy, i.e. there is no parent-child relationship between them, you will get compile time error. On the other hand, if you typecast objects from same type hierarchy but the object which you are casting are not of the same type on which you are casting then it will throw ClassCastException in Java.
Some people may ask why do you need type casting? well, you need type casting to get access to fields and methods declared on the target type or class. You can not access them with any other type. Let's see a simple example of type casting in Java with two classes Base and Derived which share the same type hierarchy.
If you try to cast two objects which don't share same type hierarchy, i.e. there is no parent-child relationship between them, you will get compile time error. On the other hand, if you typecast objects from same type hierarchy but the object which you are casting are not of the same type on which you are casting then it will throw ClassCastException in Java.
Some people may ask why do you need type casting? well, you need type casting to get access to fields and methods declared on the target type or class. You can not access them with any other type. Let's see a simple example of type casting in Java with two classes Base and Derived which share the same type hierarchy.
Type casting example in Java
In this Example of type casting in Java, we have two classes, Base, and Derived. Derived class extends Base i.e. Base is a Super class and Derived is a Subclass. So their type hierarchy looks like the following tree :
Base
|
Derived
Now look at the following code :
Base b = new Derived(); //reference variable of Base class points object of Derived class
Derived d = b; //compile time error, requires casting
Derived d = (Derived) b; // type casting Base to Derived
Derived d = b; //compile time error, requires casting
Derived d = (Derived) b; // type casting Base to Derived
Above code type casting object of a Derived class into Base class and it will throw ClassCastExcepiton if b is not an object of the Derived class. If Base and Derived class are not related to each other and doesn't part of the same type hierarchy, the cast will throw compile time error. for example, you can not cast String and StringBuffer, as they are not from same type hierarchy.
See Core Java for Impatient for more details on upcasting and downcasting of objects in Java. Cay S. Horstmann has explained key Java concepts in very nice way.
Type-casting and ClassCastExcepiton in Java
As explained in last section type casting can result in ClassCastException in Java. If the object you are casting is of different type. ClassCastException is quite common while using Java collection framework classes e.g. ArrayList, LinkedList or HashSet etc because they accept object of type java.lang.Object, which allows insertion of any object into collection. let's a real life example of ClassCastException in Java during type casting :
ArrayList names = new ArrayList();
names.add("abcd"); //adding String
names.add(1); //adding Integer
String name = (String) names.get(0); //OK
name = (String) names.get(1); // throw ClassCastException because you can not convert Integer to String
names.add("abcd"); //adding String
names.add(1); //adding Integer
String name = (String) names.get(0); //OK
name = (String) names.get(1); // throw ClassCastException because you can not convert Integer to String
In above example, we have an ArrayList of String that stores names. But we also added an incorrect name which is Integer and when we retrieve Object from the collection they are of type java.lang.Object which needs to be cast on respective for performing the operation.
This leads into java.lang.ClassCastException, when we try to type, cast the second object, which is an Integer, into String. This problem can be avoided by using Generics in Java which we will see in next section.
You can also perform casting with primitive data types e.g. casting a long variable into an int, casting a double variable into a float, or casting an int variable into char, short and byte data type. This is known as down-casting in Java. See these core Java online courses for more details on type casting of primitive and reference type in Java.
You can also perform casting with primitive data types e.g. casting a long variable into an int, casting a double variable into a float, or casting an int variable into char, short and byte data type. This is known as down-casting in Java. See these core Java online courses for more details on type casting of primitive and reference type in Java.
Generics and Type Casting in Java
Generics was introduced in Java 5 along with another type-safe feature Enum, which ensures type safety of code during compile time, So rather you getting ClassCastException during runtime by type casting you get compile timer error why your code violates type safety. Use of Generics also removes casting from many places e.g. now while retrieving an object from Collection you don't need to typecast into respective type.
Here is the modified version of same code which is free of ClassCastException because of the use of Generics :
ArrayList<String> names = new ArrayList<String>(); //ArrayList of String only accept String
names.add("abcd");
names.add(1); //compile time error you can not add Integer into ArrayList of String
String name = names.get(0); // no type casting requires
names.add("abcd");
names.add(1); //compile time error you can not add Integer into ArrayList of String
String name = names.get(0); // no type casting requires
If you are new to Generics, those angle bracket denotes type. to learn more about Generics, See How Generics works in Java.
In this Java tutorial, we learn What is type casting in Java, how to cast one class to another class or interface in Java with a simple type casting Example. We have also seen the risk of ClassCastException related to type casting and How can we reduce that risk by using Generics in Java. In Summary, minimize type casting in Java program and use type-safe Enum and Generics to reduce or completely eliminate type casting from Java code.
Other Java fundamental tutorials from Javarevisited Blog
Should it not be
ReplyDeleteDerived d =(Derived) b;
in your first code block.
@Anonymous, you are right. Thanks for pointing it out.
ReplyDeleteAvoid Type casting if you can by using Generics and proper types, because type casting make your code fragile, as it violate an important object oriented programming guideline "Coding for interface than implementation". If you must need to type cast, then type cast in a interface rather than implementation as shown below :
ReplyDeleteTag tag = (Tag) getElement("h1");
tag.process();
Instead of
H1 h1 = (H1) getElement("h1");
h1.process();
but this is only possible if process method is defined in the Tag interface. So always use API methods outside the class, and only use implementation method inside class. Type casting can break your code, if you are going to support multiple implementation later.
class Parent{
ReplyDeletevoid A(){ System.out.println("Parent");}
}
class Child extends Parent{
@Override
void A(){ System.out.println("Child");}
}
public class Test2 {
public static void main(String[] args) {
Parent p = new Parent();
Child c = (Child) p;
c.A();
}
}
Why is this showing an error. Cant we cast from Higher to lower. How is then Object being cast to the sub types.
well you need type casting to get access of fields and methods declared on target type or class. You can not access them with any other type
ReplyDeletepackage iTest;
ReplyDeletepublic class MyTest {
public static void main(String[] args){
B2 b=null;
A2 obj=new A2();
//B2 obj3=(B2)new A2();// Child can't Hold parent object
b=(B2)new A2();
}
}//class
class A2{
public void show(){
System.out.println("A2--->show()");
}
/*public void hello(){
System.out.println("A2--->hello()");
}*/
}
class B2 extends A2{
public void show(){
System.out.println("B2--->show()");
}
public void hai(){
System.out.println("B2--->hai()");
}
}
Can any one tell me how to hold parent object by child reference
Can anyone explain about ClassCastException in detail please...
ReplyDeleteI have explained it on my post ClassCastException vs NoClassDefFoundError You may want to check that.
ReplyDeleteAs you've mentioned generics is introduced to compile time type safety. I can write below code, which will get compiled but still will fail with classcastexception. Now if you say, type safety is at both compile and runtime, then generics is not fully enforcing the compile time type safety, but it will just provide way to enforce it in certain areas. Correct me if I'm wrong.
ReplyDeleteList list = new List<>();
list.add(1);
List list1 = (List) list;
list1.add("String");
for(String s:list1){
System.out.println(s);
}
Yes, you can circumvent Generics checks by writing the code like you did, but that's not the purpose. Everything after compilation is raw type to remain backward compatible.
ReplyDelete