Java  

Casting and Converting

Introduction

Casting is used to convert the value of one type to another. Casting is the mechanism of converting the value of an object or primitive type into another type. The result of the cast is a new reference or value. Instances of a class can be cast to instances of other classes. There is only one restriction the class of object being cast, and the class to which it is being cast must be related by inheritance.

Casting

Casting does not affect the original object or value. The concept that is involved in casting is simple enough, but for the fact that Java has both primitives and object types. Casting is of three types namely, casting between primitive types, casting between object types, and converting primitive types to objects and then extracting primitive values out of those objects.

Casting Primitive Types

Casting between primitive types allow conversion of non-primitive type to another. This occurs commonly between numeric types. Boolean values cannot be cast into any other primitive types. If the casting is between a type larger than the type of value being converted, then an explicit cast need not be used. The larger type provides more precision than the smaller type, and hence, no information is lost when the value is cast. The casting of integers into floating-point values or an int to a float may cause some loss of precision. To convert a larger value into a smaller one, an explicit cast must be used. Converting the value results in a loss of precision. Precedence of casting is higher than that of arithmetic operations. A typical cast from a higher value to a lower value is.

(int) (d/t);

The source code explains casting between primitive types.

class Convert {
    double x;
    double y;
    int z;

    void prod(double a, double b) {
        x = a;
        y = b;
        z = (int) (a * b);
    }

    void print() {
        System.out.println("The value is " + z);
    }

    public static void main(String args[]) {
        Convert con = new Convert();
        con.prod(10.94, 94.30);
        con.print();
    }
}

class A { }

class B extends A { }

class C extends A { }

public class InvalidCast {
    public static void main(String[] args) {
        A obj = new B();
        C wrongCast = (C) obj; // Unsafe cast
    }
}

Output

Convert

This example accepts two double values, calculates its product using the method prod(). The resulting value is printed using the print() method, as an integer by casting the result value.

Casting Objects

Instances of a class can be cast to instances of other classes. There is only one restriction: the class of the object being cast and the class to which it is being cast must be related by inheritance. Some objects may not be explicitly cast. An instance of a subclass can be used anywhere a superclass is expected because a subclass contains all the information that a superclass contains. Casting an object to an instance of one of that object’s superclasses loses the information the original subclass provided and requires a specific cast. To cast an object to another class, use

ClassName object;

The classname is the name of the class we want to cast the object to. Object is a reference to the object being cast. Casting creates a reference to the old object of the type classname, and the old object continues to exist.

As we know, casting is the process of converting one type to another. When it comes to object casting, this typically occurs between classes that share an inheritance relationship. A subclass object can be assigned to a superclass reference without explicit casting. This is known as up-casting. However, when we want to access subclass-specific methods from a superclass reference, we need to explicitly downcast the object back to its subclass.

Consider the following example.

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }

    void fetch() {
        System.out.println("Dog fetches the ball");
    }
}

public class TestCasting {
    public static void main(String[] args) {
        Animal a = new Dog(); // Upcasting
        a.sound();            // Calls overridden method

        Dog d = (Dog) a;      // Downcasting
        d.fetch();            // Access Dog-specific method
    }
}

Output

Testcasting

In the above code, the object a is of type Animal but refers to an instance of Dog. While the sound() method works due to polymorphism, accessing fetch() requires down-casting. The output confirms this behavior, displaying Dog barks followed by Dog fetches the ball.

However, improper casting can lead to runtime exceptions. For instance, if we try to cast an object of a subclass into an unrelated subclass, Java will throw a ClassCastException. This is shown below:

class A { }
class B extends A { }
class C extends A { }
public class InvalidCast {
    public static void main(String[] args) {
        A obj = new B();
        C wrongCast = (C) obj; // Unsafe cast
    }
}

This code compiles but fails at runtime since obj refers to a B object, and we’re trying to cast it to C, which is not allowed. A safer approach is to use the instanceof operator to check compatibility before casting.

Converting Primitive Types to Objects

Moving on to converting primitive types to objects, Java provides wrapper classes in the java.lang package such as Integer, Double, Boolean, etc., to encapsulate primitive values into objects. This process is known as autoboxing.

Converting primitive types to objects cannot be done explicitly. Primitive types and objects are two distinct things. Java.lang.package includes several special class that correspond to each primitive type. For example, Integer for int, Float for float , Boolean for boolean etc. These classes can be used to create objects that encapsulate the primitive types. To convert the values back into the primitive values, we have methods that can be utilized.

Here's a simple example.

public class PrimitiveToObject {
    public static void main(String[] args) {
        int num = 100;

        Integer obj = num;           // Autoboxing
        int result = obj.intValue(); // Unboxing

        System.out.println("Integer Object: " + obj);
        System.out.println("Primitive int: " + result);
    }
}

Output

Integer

In this example, the primitive int value 100 is converted into an Integer object automatically (autoboxing). Later, we retrieve the primitive value back using the intValue() method (unboxing). Both values are printed and show the same result.

Additionally, you can manually wrap primitives using wrapper constructors, although this is less common in modern Java due to autoboxing.

public class ManualWrapping {
    public static void main(String[] args) {
        double pi = 3.14159;

        Double piObj = new Double(pi);        //Manual wrapping
        double primitivePi = piObj.doubleValue(); //Manual unboxing

        System.out.println("Wrapped Object: " + piObj);
        System.out.println("Unwrapped Value: " + primitivePi);
    }
}

Output

Output

This demonstrates how primitive values like double can be wrapped in their object equivalents (Double) and later unwrapped using appropriate methods. These wrapper classes are particularly useful when working with collections like ArrayList, which only store objects, not primitives.

Summary

The article explains the concept of casting and converting in Java, focusing on converting data types either between primitive types or between objects. Casting involves converting a value from one type to another, especially when objects are related by inheritance. It includes casting primitive types (e.g., double to int), casting objects (e.g., subclass to superclass and vice versa), and highlights the rules and risks like ClassCastException. The document also discusses autoboxing, where primitive types are converted to objects using wrapper classes like Integer, Double, etc., and unboxing them back to primitives when needed. Practical examples illustrate each concept, such as int to Integer, Animal to Dog, and safe/unsafe casting scenarios.