Reading — step 1 of 7
Learn
Java is statically typed — every variable has a type fixed at declaration. The compiler catches type errors before your code runs. Coming from Python or JavaScript, this feels strict. The payoff: bugs caught at compile time instead of 3am production incidents.
The 8 primitive types
Java distinguishes between primitives (raw values) and objects (allocated on the heap):
// Whole numbers — different sizes:
byte b = 100; // 8-bit
short s = 30000; // 16-bit
int count = 5; // 32-bit ← most common
long big = 10_000_000_000L; // 64-bit (note the L suffix)
// Decimals:
float f = 3.14f; // 32-bit (note the f suffix)
double pi = 3.14; // 64-bit ← most common
// Single character (16-bit, supports Unicode):
char letter = 'A'; // single quotes for chars
// Truth value:
boolean active = true;
Use the underscores in numeric literals (10_000_000_000L) for readability — Java ignores them.
Strings are NOT primitives
String is a class — an object with methods. Strings ALWAYS use double quotes:
String name = "Alice";
int length = name.length();
String upper = name.toUpperCase();
Single quotes are for char (one character). Double quotes are for String. Mixing them up is a compile error.
Wrapper classes — for when you need objects
Every primitive has a corresponding wrapper class:
| Primitive | Wrapper |
|---|---|
| int | Integer |
| long | Long |
| double | Double |
| boolean | Boolean |
| char | Character |
These are needed because generic types and collections work with objects, not primitives:
Integer n = 42; // boxes the int
List<Integer> nums = new ArrayList<>(); // primitives can't be in generics
nums.add(5); // auto-boxed to Integer
Auto-boxing converts between primitive and wrapper automatically. Mostly invisible — but performance-sensitive code prefers primitives.
Casting between types
Java is strict. Conversions that LOSE precision require an explicit cast:
int a = 5;
long b = a; // OK — int → long widens, no loss
double d = a; // OK — int → double widens
double pi = 3.14;
int truncated = (int) pi; // ✓ explicit cast — drops decimal
// int n = pi; // ✗ compile error — would lose data
The (type) syntax is a cast. Required for narrowing conversions (long → int, double → int).
Final — Java's const
final int MAX = 100;
MAX = 200; // ✗ compile error — reassignment forbidden
final prevents reassignment. For object references, the reference is final but the object's contents can still be mutated:
final List<Integer> nums = new ArrayList<>();
nums.add(5); // ✓ mutating the list is fine
nums = null; // ✗ but reassigning the variable isn't
var — type inference (Java 10+)
var x = 5; // x is int (inferred from 5)
var name = "Alice"; // name is String
var list = new ArrayList<Integer>();
var only works for local variables with an initializer. The variable is still statically typed — Java just figures out the type from the right side.
Default values for fields
Uninitialized class fields get default values:
- Numeric primitives:
0 boolean:false- Object references (including String):
null
LOCAL variables (inside methods) have NO default — using one before assignment is a compile error.
Naming conventions
- Variables, methods: camelCase —
userName,getMaxValue() - Classes: PascalCase —
BankAccount,UserRepository - Constants: UPPER_SNAKE_CASE —
MAX_RETRIES,PI
Common mistakes
- Forgetting the
Lfor long literals:long big = 10000000000;is a compile error — the literal overflows int. Use10000000000L. - Mixing
'and":'hello'is invalid (chars are single character). Use"hello". - Using
==to compare Strings — checks reference identity, not contents. Use.equals(). (More on this in Strings lesson.) - Auto-unboxing a
nullInteger — NullPointerException.Integer n = null; int x = n;crashes.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…