Java Type Casting and Type Conversion

Convert between different data types like converting dollars to euros - change the form while keeping the value

What is Type Casting and Conversion?

Type casting (or type conversion) is the process of changing a variable from one data type to another. Imagine you have a number as text ("123") and need to use it as an integer in calculations. Type conversion is how you transform it!

  • Type Casting: Converting one primitive data type to another (int to double, long to int, etc.)
  • Type Conversion: Changing between different data types, including objects (String to int, int to String, etc.)
  • Why it matters: Programs often receive data in one format but need it in another format

Real-Life Analogy: Converting between currencies - you have 100 dollars and want to know the value in euros. The amount changes form, but it represents the same value.

Two Types of Casting

1. Widening Casting (Automatic)

Converting a smaller data type to a larger data type. This is safe because no data is lost. Java does this automatically for you!

Order (smallest to largest): byte → short → int → long → float → double

Example: Converting int (32 bits) to long (64 bits) - the long container is bigger, so everything fits perfectly.

2. Narrowing Casting (Manual)

Converting a larger data type to a smaller data type. This is risky because data might be lost. You must do this manually by typing the desired type in parentheses.

Order (largest to smallest): double → float → long → int → short → byte

Example: Converting double (64 bits) to int (32 bits) - you might lose decimal information.

Widening Casting: Small to Large (Automatic)

Widening is automatic and safe. Java converts smaller types to larger types without you asking:

Example: Automatic Widening Conversion

public class WideningExample {
    public static void main(String[] args) {
        // int to long (automatic)
        int myInt = 100;
        long myLong = myInt;  // No casting needed!
        System.out.println("int: " + myInt);
        System.out.println("long: " + myLong);
        
        System.out.println("");
        
        // int to double (automatic)
        int number = 50;
        double result = number;  // Automatically converts
        System.out.println("int: " + number);
        System.out.println("double: " + result);
        
        System.out.println("");
        
        // byte to int (automatic)
        byte myByte = 10;
        int intValue = myByte;  // Safe conversion
        System.out.println("byte: " + myByte);
        System.out.println("int: " + intValue);
    }
}
Output:
int: 100
long: 100

int: 50
double: 50.0

byte: 10
int: 10

Explanation:

  • No explicit casting syntax needed - Java handles it automatically
  • The value remains unchanged during conversion
  • No data is lost because the destination type is always larger
  • Safe and convenient for implicit (automatic) conversions

Narrowing Casting: Large to Small (Manual)

Narrowing requires you to explicitly specify the target type in parentheses. It's manual because it can be risky - you might lose data!

Example: Manual Narrowing Conversion

public class NarrowingExample {
    public static void main(String[] args) {
        // double to int (loses decimal part)
        double myDouble = 9.78;
        int myInt = (int) myDouble;  // Casting required!
        System.out.println("double: " + myDouble);
        System.out.println("int: " + myInt);  // Decimal is lost
        
        System.out.println("");
        
        // long to int (might lose data if number too large)
        long myLong = 500L;
        int intValue = (int) myLong;  // Manual cast
        System.out.println("long: " + myLong);
        System.out.println("int: " + intValue);
        
        System.out.println("");
        
        // int to byte (might lose data)
        int largeNumber = 300;
        byte byteValue = (byte) largeNumber;  // Data loss possible
        System.out.println("int: " + largeNumber);
        System.out.println("byte: " + byteValue);  // Unexpected result!
    }
}
Output:
double: 9.78
int: 9

long: 500
int: 500

int: 300
byte: 44

Explanation:

  • (int) and (byte) are explicit casting - you tell Java what type you want
  • 9.78 becomes 9 because int can't store decimals (not rounded, just removed)
  • 300 to byte becomes 44 because byte can only hold values -128 to 127 (data overflow)
  • Use narrowing casting carefully to avoid losing important information

Converting Strings to Numbers

Often you receive data as strings (from user input or files) but need them as numbers. Use special conversion methods for this:

1. String to Integer: Integer.parseInt()

Converts a String to an int. The string must contain valid digits like "123".

Syntax: int num = Integer.parseInt("123");

2. String to Double: Double.parseDouble()

Converts a String to a double. The string can include a decimal point like "45.67".

Syntax: double num = Double.parseDouble("45.67");

3. String to Long: Long.parseLong()

Converts a String to a long. Good for very large numbers.

Syntax: long num = Long.parseLong("999999999");

4. String to Boolean: Boolean.parseBoolean()

Converts a String to a boolean. Only "true" (any case) returns true.

Syntax: boolean flag = Boolean.parseBoolean("true");

String to Number Conversion Examples

Here are practical examples of converting strings to numbers:

Example: Converting Strings to Different Number Types

public class StringToNumberExample {
    public static void main(String[] args) {
        // String to int
        String str1 = "456";
        int number = Integer.parseInt(str1);
        System.out.println("String: \"" + str1 + "\" → int: " + number);
        System.out.println("Type: " + number + " is an integer");
        
        System.out.println("");
        
        // String to double
        String str2 = "89.99";
        double price = Double.parseDouble(str2);
        System.out.println("String: \"" + str2 + "\" → double: " + price);
        System.out.println("Can perform math: " + price * 2);
        
        System.out.println("");
        
        // String to long
        String str3 = "999888777";
        long bigNumber = Long.parseLong(str3);
        System.out.println("String: \"" + str3 + "\" → long: " + bigNumber);
        
        System.out.println("");
        
        // Practical use: calculating from user input
        String userAge = "25";
        String userSalary = "50000.50";
        int age = Integer.parseInt(userAge);
        double salary = Double.parseDouble(userSalary);
        double bonus = salary * 0.10;
        System.out.println("Age: " + age);
        System.out.println("Salary: $" + salary);
        System.out.printf("Bonus (10%%): $%.2f%n", bonus);
    }
}
Output:
String: "456" → int: 456
Type: 456 is an integer

String: "89.99" → double: 89.99
Can perform math: 179.98

String: "999888777" → long: 999888777

Age: 25
Salary: $50000.5
Bonus (10%): $5000.05

Explanation:

  • Integer.parseInt() converts the string "456" to the integer 456
  • Double.parseDouble() converts "89.99" to the decimal number 89.99
  • After conversion, you can perform mathematical operations
  • Very useful when reading user input or data from files as strings

Converting Numbers to Strings

Sometimes you need to convert numbers to strings for display, concatenation, or storage. There are several ways to do this:

1. Using String.valueOf()

Converts any data type to a String. Universal method that works for all types.

Syntax: String str = String.valueOf(123);

2. Using toString()

Converts most number objects (Integer, Double, Long) to String.

Syntax: String str = Integer.toString(123);

3. Using String Concatenation

Simply add the number to an empty string. Java automatically converts it.

Syntax: String str = "" + 123;

Number to String Conversion Examples

Example: Converting Numbers to Strings

public class NumberToStringExample {
    public static void main(String[] args) {
        // Method 1: String.valueOf()
        int age = 25;
        String ageStr = String.valueOf(age);
        System.out.println("int " + age + " → String: \"" + ageStr + "\"");
        
        System.out.println("");
        
        // Method 2: toString()
        double price = 99.99;
        String priceStr = Double.toString(price);
        System.out.println("double " + price + " → String: \"" + priceStr + "\"");
        
        System.out.println("");
        
        // Method 3: String concatenation
        int score = 95;
        String scoreStr = "" + score;  // Automatic conversion
        System.out.println("int " + score + " → String: \"" + scoreStr + "\"");
        
        System.out.println("");
        
        // Practical use: building messages
        int orderID = 12345;
        double totalCost = 150.75;
        String message = "Order #" + orderID + " - Total: $" + totalCost;
        System.out.println(message);
        
        // Verifying type change
        System.out.println("");
        System.out.println("ageStr is a String: " + ageStr.getClass().getSimpleName());
        System.out.println("scoreStr is a String: " + scoreStr.getClass().getSimpleName());
    }
}
Output:
int 25 → String: "25"
double 99.99 → String: "99.99"
int 95 → String: "95"

Order #12345 - Total: $150.75

ageStr is a String: String
scoreStr is a String: String

Explanation:

  • String.valueOf() is the most common and reliable method
  • toString() works well with wrapper classes like Integer, Double, Long
  • String concatenation with "" is convenient but less efficient for many conversions
  • Perfect for building messages, file names, or user-friendly output

Complete Example: Currency Converter

Let's create a practical program that reads currency values as strings and converts them to perform calculations:

Example: Currency Conversion with Type Changes

import java.util.Scanner;

public class CurrencyConverter {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Read dollar amount as string
        System.out.print("Enter amount in USD: ");
        String dollarStr = scanner.nextLine();
        
        // Convert string to double
        double dollars = Double.parseDouble(dollarStr);
        
        // Conversion rates
        double rateEUR = 0.92;   // 1 USD = 0.92 EUR
        double rateINR = 83.5;   // 1 USD = 83.5 INR
        
        // Calculate conversions
        double euros = dollars * rateEUR;
        double rupees = dollars * rateINR;
        
        // Convert results back to strings for display
        String eurosStr = String.format("%.2f", euros);
        String rupeesStr = String.format("%.2f", rupees);
        
        // Display results
        System.out.println("\n--- Currency Conversion ---");
        System.out.println("USD: $" + dollars);
        System.out.println("EUR: €" + eurosStr);
        System.out.println("INR: ₹" + rupeesStr);
        
        scanner.close();
    }
}
Output (with user input):
Enter amount in USD: 100
--- Currency Conversion ---
USD: $100.0
EUR: €92.00
INR: ₹8350.00

Explanation:

  • User input comes as a string, converted to double with parseDouble()
  • Mathematical operations performed on the double values
  • Results formatted as strings for clean display using String.format()
  • Demonstrates the complete cycle: String → Number → Calculation → String

Type Casting in Operations

Java automatically performs type casting in mathematical operations. Larger types "win" when mixed:

Example: Automatic Type Conversion in Math

public class OperationCastingExample {
    public static void main(String[] args) {
        // int + int = int
        int a = 10;
        int b = 20;
        int result1 = a + b;
        System.out.println("int + int = " + result1);
        System.out.println("Result type: int");
        
        System.out.println("");
        
        // int + double = double (int auto-converts to double)
        int num1 = 15;
        double num2 = 25.5;
        double result2 = num1 + num2;
        System.out.println("int + double = " + result2);
        System.out.println("Result type: double");
        
        System.out.println("");
        
        // Division with integers (common mistake)
        int x = 7;
        int y = 2;
        int divInt = x / y;  // Result is 3, not 3.5
        System.out.println("7 / 2 (both int) = " + divInt);
        
        System.out.println("");
        
        // Division with casting (correct way)
        double divDouble = (double) x / y;  // Converts to 3.5
        System.out.println("7 / 2 (cast to double) = " + divDouble);
        
        System.out.println("");
        
        // byte + byte = int (small types convert to int)
        byte b1 = 10;
        byte b2 = 20;
        int resultByte = b1 + b2;  // Result is int, not byte!
        System.out.println("byte + byte = " + resultByte);
        System.out.println("Result type: int (not byte!)");
    }
}
Output:
int + int = 30
Result type: int

int + double = 40.5
Result type: double

7 / 2 (both int) = 3

7 / 2 (cast to double) = 3.5

byte + byte = 30
Result type: int (not byte!)

Explanation:

  • When you mix int and double, Java automatically converts int to double
  • 7 / 2 with integers gives 3 (decimal part is dropped)
  • Cast to double first to get accurate decimal result: 7.0 / 2 = 3.5
  • byte + byte results in int (not byte!) because Java promotes small types in operations

Common Type Casting Mistakes

❌ Mistake 1: Invalid String to Number Conversion

Converting "abc" to int causes an error. The string must contain valid digits only: Integer.parseInt("abc"); → Error!

❌ Mistake 2: Forgetting Parentheses in Narrowing

Narrowing casting requires parentheses: int x = (int) 9.5; not int x = int 9.5;

❌ Mistake 3: Integer Division Loss

Dividing two integers loses decimal places. Always cast to double: double result = (double) 7 / 2; not int result = 7 / 2;

❌ Mistake 4: Overflow in Narrowing

Converting 300 to byte gives wrong results because byte range is -128 to 127. The number "wraps around".

❌ Mistake 5: Precision Loss with Decimals

Converting 9.99 to int gives 9 (decimal is removed, not rounded). Use Math.round() if you need proper rounding.

Solutions: Handling Errors Properly

Example: Safe Type Conversions

public class SafeConversions {
    public static void main(String[] args) {
        // Safe: Check if string is valid before converting
        String userInput = "123abc";
        try {
            int number = Integer.parseInt(userInput);
            System.out.println("Success: " + number);
        } catch (NumberFormatException e) {
            System.out.println("❌ Error: \"" + userInput + "\" is not a valid number");
        }
        
        System.out.println("");
        
        // Safe: Use double for division to preserve decimals
        int numerator = 7;
        int denominator = 2;
        double correctDivision = (double) numerator / denominator;
        System.out.println("7 / 2 = " + correctDivision);  // 3.5
        
        System.out.println("");
        
        // Safe: Use Math.round() for proper decimal rounding
        double value = 9.78;
        long rounded = Math.round(value);  // Rounds to 10
        System.out.println("Math.round(" + value + ") = " + rounded);
        
        System.out.println("");
        
        // Safe: Check range before narrowing
        long largeNum = 500L;
        if (largeNum >= Byte.MIN_VALUE && largeNum <= Byte.MAX_VALUE) {
            byte safeByte = (byte) largeNum;
            System.out.println("Safe conversion to byte: " + safeByte);
        } else {
            System.out.println("❌ " + largeNum + " is too large for byte (-128 to 127)");
        }
    }
}
Output:
❌ Error: "123abc" is not a valid number

7 / 2 = 3.5

Math.round(9.78) = 10

Safe conversion to byte: 500

Explanation:

  • Use try-catch to handle invalid string conversions gracefully
  • Always cast to double for decimal division: (double) numerator / denominator
  • Use Math.round() to properly round decimals before converting to int
  • Check value ranges before narrowing to prevent overflow errors