Java Fundamentals

Type Casting & Conversion

15 min Lesson 5 of 14

Type Casting & Conversion

In the previous lessons you declared variables with specific types: int, double, long, and so on. Real programs constantly move data between those types — storing a measured temperature (a double) in an integer field, reading user input (always a String) and treating it as a number, or keeping a running total in a long even though individual counts are int values. This lesson covers every mechanism Java gives you to do that safely.

Two Directions: Widening and Narrowing

Think of the primitive numeric types arranged by size, smallest to largest:

byte (8-bit) ↓ widening (safe, automatic) short (16-bit) ↓ int (32-bit) ↓ long (64-bit) ↓ float (32-bit IEEE 754) ↓ double (64-bit IEEE 754)

Widening moves up the chain — a smaller type fits perfectly into a larger container, so no information is lost. Java performs widening automatically (implicitly). Narrowing moves down — forcing a large value into a smaller container may lose data, so Java requires you to write an explicit cast.

Implicit (Widening) Conversion

No cast syntax is needed. Java does the work for you:

int score = 95; long big = score; // int → long, automatic double exact = score; // int → double, automatic float approx = score; // int → float, automatic System.out.println(big); // 95 System.out.println(exact); // 95.0
Why does widening always work? Every value that fits in 32 bits also fits in 64 bits — there is simply more room. The number itself does not change; the representation just uses more memory.

Explicit (Narrowing) Cast

When you want to go the other direction you write the target type in parentheses before the value:

double temperature = 36.78; int rounded = (int) temperature; // explicit cast System.out.println(rounded); // 36 ← decimal part is truncated, NOT rounded

The syntax is (targetType) expression. The cast does not round; it truncates — the fractional part is simply discarded.

Truncation, not rounding. (int) 36.99 gives 36, not 37. If you need proper rounding, use Math.round() first, which returns a long you can then cast to int.
double temperature = 36.78; int rounded = (int) Math.round(temperature); System.out.println(rounded); // 37

Integer Overflow

The most dangerous aspect of narrowing is overflow: when a value is too large to fit in the target type, the bits are simply cut off and you get a wrong — but silently wrong — result:

long bigNumber = 3_000_000_000L; // 3 billion — too large for int int overflow = (int) bigNumber; System.out.println(overflow); // -1294967296 ← garbage!

Java does not throw an exception here. It silently wraps around. The rule is simple: always check that the value fits in the target type before casting.

Use Integer.MAX_VALUE and Integer.MIN_VALUE to know the safe range: 2_147_483_647 and -2_147_483_648. Each primitive wrapper class (Long, Short, Byte) has equivalent constants.

char and Numeric Types

A char stores a Unicode code point — an unsigned 16-bit integer. It participates in widening and narrowing just like numeric types:

char letter = 'A'; int code = letter; // widening: char → int System.out.println(code); // 65 (Unicode code point for 'A') int value = 66; char back = (char) value; // narrowing: int → char System.out.println(back); // B

Parsing Strings to Numbers

Scanner gives you a raw String from the command line (or a file). To do arithmetic you must parse that string into a numeric type. Each wrapper class provides a parse* static method:

String input = "42"; int n = Integer.parseInt(input); System.out.println(n + 10); // 52 String price = "19.99"; double amount = Double.parseDouble(price); System.out.println(amount * 2); // 39.98 String big = "9876543210"; long lValue = Long.parseLong(big); System.out.println(lValue); // 9876543210
Bad input throws NumberFormatException. If the string is not a valid number — for example "12abc" or an empty string — parseInt crashes at runtime. You will learn to handle this with try-catch in the Exceptions tutorial.

Converting Numbers Back to Strings

Going the other way — turning a number into a String — is always safe and never requires a cast. Three common idioms:

int count = 100; String s1 = String.valueOf(count); // recommended String s2 = Integer.toString(count); // also fine String s3 = "" + count; // works, but less expressive System.out.println(s1.getClass().getSimpleName()); // String

Summary

Widening conversions are automatic and safe. Narrowing conversions require an explicit cast, truncate decimals, and can silently overflow — always verify the value fits first. Use Integer.parseInt, Double.parseDouble, and their siblings to convert String input into numbers, and guard against invalid strings. These patterns appear in nearly every Java program you will ever write.