Skip to content

VOL 01 / CH 02 / LESSON 01

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:

bash
chapter2_workdir=$(mktemp -d)
readonly chapter2_workdir
cd "$chapter2_workdir"
java
public class VariablesDemo {
    public static void main(String[] args) {
        int score = 95;
        System.out.println(score);

        score = 98;
        System.out.println(score);
    }
}
bash
mkdir -p out
javac -d out VariablesDemo.java
java -cp out VariablesDemo

Expected output:

text
95
98

int score = 95; simultaneously accomplishes three things:

PartMeaning
intDeclares the type as a 32-bit signed integer
scoreDeclares the variable name
= 95Assigns 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:

java
int count;      // Declaration
count = 1;      // First assignment also completes initialization
count = 2;      // Reassign value

Local variables do not have automatically readable default values. The compiler performs an "definite assignment" check:

java
int count;
System.out.println(count); // Compilation error: may not have been initialized

Fields 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 ​

java
int level = 1;
level = 2;       // Legal: value changed, type unchanged
// level = "two"; // Compilation error:String Cannot assign to int

Java 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:

python
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:

java
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 scope

Narrowing 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 ​

java
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:

java
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:

java
var name = "Alice"; // String
var count = 42;      // int
var rate = 0.5;      // double

Type inference occurs at compile time, and the result remains a definite static type:

java
var count = 42;
// count = "forty-two"; // Compilation error

Common limitations:

java
// var missing;        // No initializer, cannot infer
// var unknown = null; // Separate null No inferable target type

var 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 ​

java
final int maxAttempts = 3;
// maxAttempts = 4; // Compilation error

A 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:

java
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 ​

java
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 l and O, which can easily be confused with numbers;
  • Names describe business meaning and do not repeat types, such as age is more natural than intAge.

Professional Quick Reference ​

QuestionJudgment
Can local variables be read if they are not initializedNo, the compiler performs definite assignment checks
Can variables change typeThe static type remains unchanged after declaration
var Is it a dynamic typeNo, the fixed type is inferred at compile time
String Is it a primitive typeNo, it is a reference type
When is a name visibleFrom the declaration point to the end of its scope, subject to rules such as shadowing
final What does it mean for a referenceA 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:

bash
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.

Built with VitePress | Software Systems Atlas