A Java variable gives a name and a type to a value your program needs. An identifier is the name used for a variable, method, class or another declared element. A final variable can be assigned only once; this is useful when a reference or value must not be reassigned.
These ideas overlap, but they are not interchangeable. A name can be syntactically valid and still be difficult to understand. A final reference can still point to a mutable object. Learn the separate rules before treating every capitalized name as an unchangeable constant.
Declare a name with a type and value
In int availableSeats = 24;, int is the type, availableSeats is the identifier and 24 is the initializer. A later assignment can replace the stored value if the variable is not final. Java checks that an assigned value is compatible with the declared type; you cannot assign a string to an int variable simply because its characters look numeric.
Declare variables near their first use and name them after the information they hold. A name such as availableSeats is more useful than x when the value represents seating capacity. Include units where ambiguity matters, such as timeoutMillis rather than timeout. A variable is not a permanent relationship between expressions: after int doubleCount = count * 2;, changing count does not automatically recalculate doubleCount.
Follow the identifier rules
An identifier cannot start with a digit and cannot be a reserved Java keyword such as class or return. Digits may appear after the first character, so level2 is valid. Java supports a broad set of Unicode letters in names, although familiar letters are usually easier for a team to type and review consistently. Underscore and dollar sign can appear in identifiers, but a single underscore has been forbidden as an identifier since Java 9.
Java names are case sensitive. total, Total and TOTAL are different identifiers. Spaces and hyphens cannot appear inside an identifier: order-total is read as subtraction, not one name. When a name is rejected, fix the name rather than surrounding it with quotes; quotes create a string literal. Contextual language features have additional restrictions, so avoid unusual names such as var for types.
Use conventions to communicate purpose
Variables and methods conventionally use lower camel case, such as customerCount and calculateTotal. Class names conventionally use upper camel case, such as DeliveryRequest. True constant fields commonly use uppercase words separated by underscores, such as MAX_ATTEMPTS. These conventions help readers identify a name’s role without being rules that change execution.
Initialization and definite assignment
A local variable declared inside a method must receive a value before you read it. Writing int score; declares the name but does not initialize a usable score. The compiler analyzes the available paths and rejects a read that might occur before assignment. If two branches both assign a value, the read after those branches can be valid.
Fields have default values when an object or class is initialized: numeric fields start at zero, boolean fields at false and reference fields at null unless another initializer supplies a value. This differs from uninitialized local variables. Do not rely on defaults when a field needs a meaningful initial state, such as a nonzero retry limit. An explicit initializer or constructor assignment makes that requirement visible.
final prevents reassignment, not every change
A final variable may be assigned only once. You can initialize it at declaration or, in permitted cases, assign it later exactly once. A final local variable is useful when a computed value should remain fixed during the rest of a method. A static final field can express a shared limit or a constant used by all instances.
For a reference variable, final fixes the reference. It does not freeze the object. A final array can still have its elements changed, and a final list can still accept new items if the list implementation allows it. To prevent those mutations, choose an immutable design or an unmodifiable view as appropriate. Also remember that not every static final field is a compile-time constant; that narrower category has additional type and initializer requirements.
Practice with explained solutions
Task 1. Choose a valid, readable name for the number of unread messages, and declare it with value 6.
Solution. int unreadMessages = 6; states both the type and purpose. Names with spaces or an initial digit are invalid.
Task 2. Explain whether final StringBuilder note = new StringBuilder("A"); permits note.append("B").
Solution. It does: the reference remains fixed while the builder changes. Assigning note to a different builder would not be allowed.
Java Summary
- Choose identifiers that explain the value's purpose, and remember that names are case-sensitive.
- final prevents reassignment; it does not make a referenced array or object immutable.
- Initialize a local variable before reading it.
- Continue with primitive types.
Java Examples
Each example shows the code, the output it produces and what each part does.
Give changing values meaningful names
Save this complete program as SeatAvailability.java. Compile with javac --release 17 SeatAvailability.java and run with java SeatAvailability.
public class SeatAvailability {
public static void main(String[] args) {
int availableSeats = 24;
int requestedSeats = 5;
availableSeats = availableSeats - requestedSeats;
System.out.println("Seats left: " + availableSeats);
}
}Seats left: 19Line-by-line explanation
- Lines 1 to 8The declaration initializes availableSeats with twenty-four. The assignment evaluates its current value minus five, then replaces that same variable with nineteen. requestedSeats is a separate variable and remains five. Writing remainingSeats as a new variable would preserve the original availableSeats instead, so choose the design that matches whether the original capacity must still be available later.
Share a fixed limit
Save this complete program as RetryLimit.java. Compile with javac --release 17 RetryLimit.java and run with java RetryLimit.
public class RetryLimit {
static final int MAX_ATTEMPTS = 3;
public static void main(String[] args) {
int attemptsUsed = 1;
int attemptsLeft = MAX_ATTEMPTS - attemptsUsed;
System.out.println(attemptsLeft);
}
}2Line-by-line explanation
- Lines 1 to 8MAX_ATTEMPTS belongs to the class because it is static and cannot be reassigned because it is final. Its uppercase name signals a constant convention. The local calculation subtracts one used attempt and prints two remaining attempts. Trying MAX_ATTEMPTS = 4 would fail compilation; printing or subtracting the constant does not change it. This example is a class body rather than statements pasted directly inside another main method.
A final array can contain changing elements
Save this complete program as FinalArray.java. Compile with javac --release 17 FinalArray.java and run with java FinalArray.
public class FinalArray {
public static void main(String[] args) {
final int[] scores = {7, 9};
scores[0] = 10;
System.out.println(scores[0]);
System.out.println(scores[1]);
}
}10
9Line-by-line explanation
- Lines 1 to 8The variable scores always refers to the same array. Assigning an element changes data inside that array, so it is legal even with final. The second element stays nine because the example changes only index zero. Replacing the entire reference with scores = new int[]{1, 2} would be illegal. This distinction prevents the common assumption that adding final makes all reachable data immutable.
Common Java Mistakes
Names that don't match what they hold
A variable named totalPrice should hold a price, not a count. If you rename only the declaration and miss its uses, the compiler reports unresolved names; use editor-assisted renaming where available. Do not initialize every number to zero just to silence definite-assignment errors. Decide what the starting value actually means, and initialize it only when that meaning is known.
Java FAQ
Are uppercase names automatically constants?
No. Capitalization is a convention; the final modifier controls reassignment. A mutable field named LIMIT can still change without final.
Should every variable be final?
Use final where one assignment reflects the intended design. A loop counter or changing balance may legitimately need reassignment, while a fixed input reference can often be final.
Can Java identifiers use letters from other languages?
Yes. Java accepts Unicode letters, so int größe = 3; compiles. In shared and open-source code, most teams stick to English names with plain ASCII letters so that everyone can type and search for them easily.
Which words can't be used as names in Java?
Reserved keywords such as class, int, return, if and new can't be identifiers, and neither can the literals true, false and null. Some newer words, such as var, record and yield, are only special in certain places: var can't name a class, for example, but it can still be used as a variable name.
What is the difference between final and static final?
A final field belongs to each object and can't be reassigned after construction, so different objects can hold different values. A static final field belongs to the class and is shared by all objects, which makes it the usual way to declare a constant such as static final int MAX_SEATS = 24;.
Java Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Why can int unreadMessages = 6 be read immediately?
Which assignment is prohibited for a final array reference?
Java Quiz
2 questions to check what you learned.
Which identifier is valid?
- 2items
- item-count
- itemCount2
What does final guarantee for an array variable?
- The reference cannot be reassigned
- Every element is immutable
- The array has no elements