Java is statically typed: every value has a type the compiler checks, so choosing types correctly is the first design decision you make.
A variable is declared with a type and a name, and must be assigned before it is read: int count = 0;. The compiler checks every assignment against that type, so count = "ten"; is a compile error.
Java has eight primitive types, which hold plain values rather than references to objects:
int(32-bit) andlong(64-bit) for whole numbers;byteandshortexist but are rarely used.double(64-bit) andfloat(32-bit) for floating-point numbers. Default todouble.booleanfortrue/false, andcharfor a single UTF-16 code unit like'A'.
Literals have types too: 42 is an int, 42L a long, 3.14 a double, 3.14f a float. Underscores improve readability: 1_000_000.
Everything else — String, arrays, your own classes — is a reference type: the variable holds a reference to an object, or null.
Since Java 10, local variables can use var and let the compiler infer the type from the initializer: var names = new ArrayList<String>();. The variable is still statically typed; var just saves typing. Use it when the type is obvious from the right-hand side, not when it hides important information.
Mark variables that should never be reassigned with final. Constants are typically static final fields: static final int MAX_USERS = 100;.
Watch the ranges: int overflows silently past about 2.1 billion, wrapping to a negative number. Use long for things like timestamps in milliseconds, and Math.addExact when overflow must be an error.
Example
public class Types {
static final double TAX_RATE = 0.2; // a constant
public static void main(String[] args) {
int items = 3;
long bytesOnDisk = 5_000_000_000L; // too big for int
double price = 19.99;
boolean inStock = true;
char grade = 'A';
var total = items * price * (1 + TAX_RATE); // inferred as double
System.out.println(total); // 71.964
System.out.println(Integer.MAX_VALUE + 1); // -2147483648 (overflow!)
System.out.println(bytesOnDisk + " " + inStock + " " + grade);
}
}Remember
- 8 primitives:
byte short int long float double boolean char; everything else is a reference varinfers a local variable's type at compile time — it is still static typingfinalprevents reassignment;static finalmakes a constant
Watch out for
- Forgetting the
Lsuffix:long big = 5000000000;does not compile because the literal is an int.