Declaring Variables
OCP Exam Topic — Understand local, instance, and class (static) variables; the
varkeyword;final; and effectively final. Covered in Chapter 1 of OCP Java SE 21 Developer Study Guide (Selikoff & Boyarsky).
Variable Categories
Java variables fall into three categories depending on where they are declared:
| Category | Declared In | Lifecycle | Default Value |
|---|---|---|---|
| Local | Method body or block | Created on entry, destroyed on exit | None — must be initialized before use |
| Instance | Class body (no static) |
Lives as long as the enclosing object | Type-specific default (0, false, null) |
| Class (static) | Class body with static |
Lives as long as the class is loaded | Type-specific default |
javapublic class Counter {
static int classCount = 0; // class variable
int instanceCount = 0; // instance variable
void increment() {
int local = 1; // local variable
instanceCount += local;
classCount += local;
}
}Local Variables
Local variables are declared inside a method, constructor, or block. They must be explicitly initialized before the compiler will let you read them — there is no default value.
javavoid show() {
int x;
// System.out.println(x); // compile error: variable x might not have been initialized
x = 10;
System.out.println(x); // fine
}Local variables declared in a for loop initializer are scoped to the loop:
javafor (int i = 0; i < 3; i++) {
System.out.println(i);
}
// System.out.println(i); // compile error — i is out of scopeInstance Variables
Instance variables belong to a specific object. They are initialized to their type's default when the object is constructed:
- Numeric types →
0(or0L,0.0f,0.0) boolean→falsechar→''- Reference types →
null
javapublic class Dog {
String name; // null by default
int age; // 0 by default
boolean trained; // false by default
}Class (Static) Variables
A static variable is shared across all instances of a class. It is initialized once when the class is first loaded:
javapublic class IdGenerator {
static int nextId = 1; // shared across all instances
int id = nextId++; // each new object gets the next id
}The var Keyword (Local Variable Type Inference)
Introduced in Java 10, var lets the compiler infer the type of a local variable from its initializer. It is syntactic sugar — the resulting bytecode is identical to using the explicit type.
javavar message = "Hello"; // inferred as String
var count = 42; // inferred as int
var items = new ArrayList<String>(); // inferred as ArrayList<String>var Limitations — Know These for the Exam
| Limitation | Reason |
|---|---|
Cannot use var without an initializer |
Type cannot be inferred |
Cannot initialize var with null alone |
No type to infer |
Cannot use var for instance or class fields |
Only allowed for local variables |
Cannot use var for method parameters |
Explicit types required |
Cannot use var in lambda parameters (without explicit types) |
Inference ambiguity |
Cannot use var for catch parameters |
Not supported |
java// These all cause compile errors:
var x; // no initializer
var y = null; // no type inferable from null
// class field:
// var name = "dog"; // not allowed in field declarations
// This is valid:
var z = (String) null; // inferred as String (explicit cast provides the type)var is not a reserved keyword — you can still name a variable or method var (though it's inadvisable):
javaint var = 5; // legal but confusing — var is a context-sensitive keywordfinal Variables
Marking a variable final means it can be assigned exactly once. Any attempt to reassign it is a compile error.
javafinal int MAX = 100;
// MAX = 200; // compile error
final String greeting;
greeting = "Hello"; // first (and only) assignment — allowed
// greeting = "Hi"; // compile error — already assignedFor reference types, final prevents reassigning the reference, not mutating the object:
javafinal List<String> names = new ArrayList<>();
names.add("Alice"); // allowed — mutating the list
// names = new ArrayList<>(); // compile error — reassigning the referenceEffectively Final
A variable is effectively final if it is never reassigned after its initial assignment, even without the final keyword. The compiler recognizes this property and allows such variables to be used inside lambda expressions and anonymous classes.
javavoid process(String input) {
String trimmed = input.trim(); // effectively final — never reassigned
Runnable r = () -> System.out.println(trimmed); // allowed
r.run();
}If you later add an assignment, the variable is no longer effectively final and the lambda use becomes a compile error:
javavoid broken(String input) {
String trimmed = input.trim();
trimmed = trimmed.toLowerCase(); // now reassigned — no longer effectively final
// Runnable r = () -> System.out.println(trimmed); // compile error
}Declaring Multiple Variables
Java allows declaring multiple variables of the same type in one statement, but each must follow the rules for that type:
javaint a = 1, b = 2, c = 3; // valid
int d, e; // valid — both uninitialized locals
// var f = 1, g = 2; // compile error — var allows only one declaration per statementKey Points to Remember
- Local variables have no default — they must be initialized before reading.
- Instance and static variables receive defaults (
0,false,null). varinfers a local variable's type from its initializer; it cannot be used for fields, method parameters, or with a plainnullinitializer.finalvariables can be assigned only once; reference-typefinalvariables still allow mutation of the referenced object.- Effectively final variables can be captured by lambdas and anonymous classes without the explicit
finalkeyword. varcannot be used in a multiple-variable declaration statement.
References
- JEP 286 — Local Variable Type Inference
- OCP Oracle Certified Professional Java SE 21 Study Guide — Chapter 1