2.1 Variables, Assignment, and Scope
Prerequisites: Complete Chapter 1
Estimated time: 25 minutes
Practice environment: JDK 17+ and Bash; files stay in a temporary directory
You are ready to continue when: You can declare, initialize, modify, and read local variables
The previous chapter printed fixed text. Here, a variable holds a score that changes from 95 to 98.
A Variable Is a Name at the Language Level
At first, you can think of variables as labeled boxes. But don't take this analogy as a physical blueprint of the JVM. Compilers and runtimes might place local variables into stack frames, registers, or even eliminate them entirely. What Java code truly promises is:
- Variables have declared types;
- Within their scope, they can be read from or assigned a value by name;
- When read, they return the current value stored in the variable.
First, create an isolated directory, then create VariablesDemo.java:
chapter2_workdir=$(mktemp -d)
readonly chapter2_workdir
cd "$chapter2_workdir"public class VariablesDemo {
public static void main(String[] args) {
int score = 95;
System.out.println(score);
score = 98;
System.out.println(score);
}
}mkdir -p out
javac -d out VariablesDemo.java
java -cp out VariablesDemoExpected output:
95
98int score = 95; simultaneously accomplishes three things:
| Part | Meaning |
|---|---|
int | Declares the type as a 32-bit signed integer |
score | Declares the variable name |
= 95 | Assigns the integer value 95 to the variable |
Writing score = 98; a second time assigns a new value, not a redeclaration. If you write int score = 98; again, it will form a duplicate local variable error within the same scope.
Declarations, Initialization, and Assignment
Do not mix the three terms:
int count; // Declaration
count = 1; // First assignment also completes initialization
count = 2; // Reassign valueLocal variables do not have automatically readable default values. The compiler performs an "definite assignment" check:
int count;
System.out.println(count); // Compilation error: may not have been initializedFields of classes and elements of new arrays receive type defaults, but that is another rule. Do not apply field defaults to local method variables.
Static Types Don't Mean Values Can't Change
int level = 1;
level = 2; // Legal: value changed, type unchanged
// level = "two"; // Compilation error:String Cannot assign to intJava is a statically typed language: the compiler checks the type of an expression before runtime, and a local variable such as level keeps its declared type; assigning a String to this int variable is a compile-time error. Static typing does not mean that all errors can be detected at compile time, nor does it mean that the value of a variable cannot be modified.
Python follows a different approach:
score = 95
score = "excellent"In Python, a name can be bound to objects of different types in sequence. Type incompatibility is usually exposed when the relevant operation is performed. Both models have tools for support and design trade-offs, and it is not appropriate to simply categorize them as "flexible" or "rigorous."
Scope Determines Where a Name Is Visible
Local variables are visible from the point of declaration within the enclosing code block:
int outer = 1;
if (outer > 0) {
int inner = 2;
System.out.println(outer + inner);
}
System.out.println(outer);
// System.out.println(inner); // Compilation error:inner Has left scopeNarrowing the scope can reduce misuse. For data that is only needed within a single if block, declare it within that block.
Meet the Eight Primitive Types
byte small = 100;
short port = 8080;
int population = 1_000_000;
long distance = 3_000_000_000L;
float ratio = 0.5F;
double temperature = 21.5;
char grade = 'A';
boolean ready = true;String is very common, but not a primitive type:
String travelerName = "Lin";Specific ranges, floating-point errors, and char Unicode boundaries will be covered in the next lesson. For now, focus on declaration shapes and common choices: prefer ordinary integers int, ordinary floating-point calculations double, and boolean conditions boolean.
var is Local Variable Type Inference
Since Java 10, the compiler can infer the type of a local variable from its initialization expression:
var name = "Alice"; // String
var count = 42; // int
var rate = 0.5; // doubleType inference occurs at compile time, and the result remains a definite static type:
var count = 42;
// count = "forty-two"; // Compilation errorCommon limitations:
// var missing; // No initializer, cannot infer
// var unknown = null; // Separate null No inferable target typevar is primarily used for local variables inside methods and can also appear in enhanced for loops and certain resource variable positions; it cannot replace field types, method parameter types, or return types. When the type is clearly visible, it is usually more appropriate to explicitly write it out for tutorials and public APIs.
final Allows a Variable to Be Assigned Only Once
final int maxAttempts = 3;
// maxAttempts = 4; // Compilation errorA blank final local variable can be initialized for the first time later, as long as the compiler can prove that all read paths have been initialized:
final int port;
port = 8080;A final reference cannot be reassigned, but the object it refers to may still be mutable. We'll explore objects in more detail later.
Naming Makes Data Roles Understandable
int retryCount = 0;
boolean connectionReady = false;
String displayName = "Lin";- Variables and methods are typically named in lowercase camel case;
- Classes and interfaces are typically named in uppercase camel case;
- Constants are typically named in uppercase with underscores, such as
MAX_RETRY_COUNT; - Avoid names like
landO, which can easily be confused with numbers; - Names describe business meaning and do not repeat types, such as
ageis more natural thanintAge.
Professional Quick Reference
| Question | Judgment |
|---|---|
| Can local variables be read if they are not initialized | No, the compiler performs definite assignment checks |
| Can variables change type | The static type remains unchanged after declaration |
var Is it a dynamic type | No, the fixed type is inferred at compile time |
String Is it a primitive type | No, it is a reference type |
| When is a name visible | From the declaration point to the end of its scope, subject to rules such as shadowing |
final What does it mean for a reference | A reference cannot be reassigned, and the object is not guaranteed to be immutable |
Before Moving On
Confirm you can distinguish declarations, initializations, and reassignments, understand why local variables cannot be read before assignment, and explain that var remains statically typed. Then clean up this page's files:
cd
ls -ld -- "$chapter2_workdir"
rm -r -- "$chapter2_workdir"The box analogy helps explain assignment; it does not promise a memory address. Next, we’ll check value ranges and where precision can be lost.
→ Next: Ranges and Boundaries of Basic Types
Specification: JLS §4.12: Variables, §14.4: Local Variable Declarations, §16: Definite Assignment.