Variables & Data Types
In Java, every variable has to declare up front what kind of value it will hold, and it can never change its mind later. That rule feels restrictive coming from a looser language, but it's what lets the compiler catch mistakes for you instead of leaving them for a user to find.
Declaring a variable
A Java variable declaration has three parts: a type, a name, and (usually) a starting value.
int studentCount = 28; double averageScore = 87.5; boolean passed = true; char grade = 'B';
Once studentCount is declared as an int, it can only ever hold whole numbers. Try to assign it 28.5 later and the compiler stops you before the program ever runs — not something you'd get away with in a dynamically typed language, where that mistake might silently corrupt a calculation three functions away from where it happened.
The primitive types
Java has eight built-in primitive types. You won't use all of them daily, but four cover almost everything:
int— a whole number, the default choice for counting things. Holds roughly -2 billion to 2 billion.double— a decimal number, the default choice for anything with a fractional part, like a price or an average.boolean—trueorfalse, nothing else. Used for yes/no conditions.char— a single character, written in single quotes like'A'. Not the same as a one-letterString, which uses double quotes.
The other four — byte, short, long, and float — exist for cases where memory size or precision matters more than convenience. long is the one you'll actually reach for occasionally, when a number is too large to fit in an int — population counts, timestamps in milliseconds, that sort of thing. It's written with an L suffix: long population = 8_100_000_000L;.
Why "primitive" is the right word
These eight types are called primitives because they hold their value directly — an int variable is the number, stored right there in memory, not a reference pointing at it somewhere else. Everything else in Java, including String and every class you write yourself, is a reference type: the variable holds a pointer to an object living elsewhere. That distinction matters more once you start passing values into methods, but for now, just notice that primitives are the lightweight, no-frills building blocks everything else is built from.
A quick grade tracker
Here's a small example that mixes several primitive types together — the kind of thing you'd write while tallying a student's results:
public class GradeSummary {
public static void main(String[] args) {
String studentName = "Marcus";
int quizScore = 82;
int examScore = 91;
double average = (quizScore + examScore) / 2.0;
boolean honorRoll = average >= 90;
System.out.println(studentName + "'s average: " + average);
System.out.println("Honor roll: " + honorRoll);
}
}
Marcus's average: 86.5 Honor roll: false
Notice the 2.0 rather than plain 2 in the division. If both sides of a division were int, Java would perform integer division and silently truncate the decimal — 173 / 2 gives 86, not 86.5. Dividing by 2.0 forces the whole expression to be treated as a double, keeping the fractional part.
Casting between types
Sometimes you need to convert a value from one type to another on purpose. Widening a type — int to double, for instance — happens automatically because no information is lost. Narrowing — double to int — requires an explicit cast, because Java wants you to acknowledge that you might be throwing away precision:
double price = 19.99; int roundedDown = (int) price; System.out.println(roundedDown);
19
Casting a double to an int doesn't round — it truncates, chopping off everything after the decimal point. 19.99 becomes 19, not 20.
final instead of a plain type keyword — like final double TAX_RATE = 0.07; — can be assigned once and never reassigned. It's Java's way of writing a constant, and the compiler will reject any later attempt to change it.