#
Casting in Java
#
Casting for primitives
In Java, for primitives we have 2 kinds of casting: widening/upcasting & narrowing/down casting.
Widening casting (Upcasting)
(could be done automatically)
double
<- float
<- long
<- int
<- short
<- byte
Widening casting
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Demo1Application.class, args);
int myInt = 7;
// Automatic casting: int -> double (no loose of data)
double myDouble = myInt;
System.out.println(myInt);
System.out.println(myDouble);
}
}
And when we run we receive:
7
7.0
Narrowing casting (Downcasting)
(must be done manually)
double
-> float
-> long
-> int
-> short
-> byte
Info
-32 768 <= short <= 32 767
-128 <= byte <= 127
Narrowing casting
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Demo1Application.class, args);
double myDouble = 7.8;
int myInt;
// Manual casting: double -> int (loose of data could exist)
myInt = (int)myDouble;
System.out.println(myInt);
System.out.println(myDouble);
}
}
And when we run we receive:
7
7.8
#
Casting for reference type variables
The main idea of the casting is the same. Please take a look at the following examples.
Casting examples
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Demo1Application.class, args);
Vehicle vehicle = new Vehicle("VE 100");
Car car = new Car("CA 100");
System.out.println("Widening casting (Upcasting)");
System.out.println("----------------------------");
Vehicle vehicle2 = car;
vehicle2.changePlateNumber("AAA");
System.out.println(" ");
System.out.println("Narrowing casting (Downcasting)");
System.out.println("----------------------------");
Car car2 = (Car) vehicle2;
car2.changePlateNumber("AAA");
car2.changeColor("Blue");
}
}
When we run the code above we will see in the console:
Widening casting (Upcasting)
----------------------------
Car :> Plate number changed.
Narrowing casting (Downcasting)
----------------------------
Car :> Plate number changed.
Car :> Change color.
Remarks
- The casting is done automatically when we have no data loss.
- The casting is done between the same variable type.
- A primitive type value can be cast to a reference type by boxing conversion.
- A reference type value can be cast to a primitive type by unboxing conversion.
Here we have a Boxing/ unboxing example:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(Demo1Application.class, args);
int x = 10;
//Boxing
Integer x1 = x;
Integer x2 = x1;
x1 = x1 * 10;
//Unboxing
int int1 = x1;
x = 8;
System.out.println("x="+x);
System.out.println("x1="+x1);
System.out.println("x2="+x2);
System.out.println("int1="+int1);
}
}
... and the result is :
x=8
x1=100
x2=10
int1=100
Remarks
- Boxing conversion creates a Wrapper Class (are the immutable classes) for a primitive. Wrapper Classes are using "pass by value" pattern, and not "pass by reference".
- The usage of the Wrapper Classes costs memory and speed, but the main reason to create wrapper classes is their usage in Collection Framework as collections can only accept objects.
- The Wrapper Classes are stored on HEAP memory as other objects from the HEAP memory is supposed to use these Wrapper Classes.