Widening conversions happen automatically; narrowing ones need an explicit cast and may silently lose information.
Widening (implicit) vs narrowing (explicit)
byte → short → int → long → float → double (char → int)
| Widening | Narrowing | |
|---|---|---|
| Direction | Smaller → larger type | Larger → smaller type |
| Syntax | Automatic: long l = i; | Cast required: int i = (int) l; |
| Data loss? | No (except precision: long/int → float/double) | Possibly: high bits dropped, fraction truncated |
public class Main {
public static void main(String[] args) {
int i = 100;
long l = i; // widening
double d = l; // widening
System.out.println(l + " " + d);
double price = 9.99;
int whole = (int) price; // truncates toward zero, not rounds
System.out.println(whole + " " + (int) -9.99 + " " + Math.round(9.5));
int big = 300;
byte b = (byte) big; // keeps only the low 8 bits: 300 - 256
System.out.println(b);
System.out.println((int) 3_000_000_000L); // high 32 bits dropped
System.out.println((int) 1e20); // double → int saturates
System.out.println((char) 97 + " " + (int) 'a');
long precise = 123_456_789_123L;
float f = precise; // widening but loses precision
System.out.println((long) f);
}
}100 100.0
9 -9 10
44
-1294967296
2147483647
a 97
123456790528Numeric promotion in expressions
In arithmetic,
byte,shortandcharare first promoted toint.If either operand is
long→long;float→float;double→double.So
byte + byteis anintand must be cast back — but compound assignments (+=) cast implicitly.
public class Main {
public static void main(String[] args) {
byte a = 10, b = 20;
// byte c = a + b; // compile error: int cannot be converted to byte
byte c = (byte) (a + b);
a += 5; // OK: means a = (byte) (a + 5)
byte x = 120;
x += 10; // silently overflows!
System.out.println(c + " " + a + " " + x);
System.out.println(5 / 2 + " " + 5 / 2.0 + " " + (double) 5 / 2 + " " + (double) (5 / 2));
System.out.println('a' + 'b' + " vs " + "" + 'a' + 'b');
}
}30 15 -126
2 2.5 2.5 2.0
195 vs abConverting to and from String
| Conversion | How |
|---|---|
String → int / double | Integer.parseInt(s), Double.parseDouble(s) (throw NumberFormatException) |
String → wrapper | Integer.valueOf(s) |
anything → String | String.valueOf(x), Integer.toString(n), "" + x |
char ↔ digit | c - '0', (char) ('0' + d), Character.getNumericValue(c) |
| radix | Integer.parseInt("ff", 16), Integer.toString(255, 2) |
public class Main {
public static void main(String[] args) {
System.out.println(Integer.parseInt("42") * 2);
System.out.println(String.valueOf(3.5) + "!");
System.out.println('7' - '0' + 1);
System.out.println(Integer.parseInt("ff", 16) + " " + Integer.toString(10, 2));
try {
Integer.parseInt("4 2");
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
}
}
}84
3.5!
8
255 1010
For input string: "4 2"Reference casting (preview)
Objects are cast along the inheritance tree: upcasting (Object o = "hi";) is implicit and always safe; downcasting (String s = (String) o;) is checked at run time and throws ClassCastException if wrong. Use instanceof pattern matching — see Polymorphism.
What is the result of (byte) 200?
Why does short s = 1; s = s + 1; fail but s += 1; compile?
Is converting long to float widening? Can it lose data?