Java Variables and Constants
Give information a useful name, follow how its value changes, and protect fixed assumptions. Build a shopping-basket summary while learning to spot both compiler errors and calculations that have become out of date.
Before you start: complete Java Output and Comments. Each example is a full Main.java program in the existing Java 21 runner. Edit one thing, predict the result, and then run it. Start with the explicit types; the optional var section can wait until the main ideas feel comfortable.
What you will be able to do
- Read a declaration as a type, a name, and an initial value.
- Initialize local variables before reading them.
- Trace assignments in order and recalculate derived values deliberately.
- Choose useful names and distinguish variables from final bindings.
- Explain the limits of final and local type inference with var.
- Build and test a basket summary using named values and integer cents.
Why give a value a name?
Last lesson, you printed fixed messages and numbers. Now imagine a basket with three notebooks. You need its quantity in a message, a price calculation, and a final summary. Repeating the number 3 everywhere makes it difficult to tell which occurrences represent the basket and which mean something else.
A variable is a named place for a value of a particular type. The name quantity tells a reader what the number represents. It also gives the program one current value to read wherever that name is in scope. A useful beginner mental model is a labelled slot: the type describes what fits, the name identifies the slot, and the value is what it currently holds.
That model is not a complete description of memory. For primitive types such as int, the value is a number; for String, the variable holds a reference to a String object. We will explore that difference later. First, learn to read declarations and follow how values change, one statement at a time.
Read a declaration: type, name, then initial value
In int quantity = 3;, int is the declared type, quantity is the variable name, and 3 is the initial value. The semicolon ends the declaration statement. Creating the name is declaration; supplying its first value is initialization. This line does both, which is usually the clearest choice when the initial value is already known.
The example uses String for text, int for a whole-number count, double for an approximate measurement, and boolean for true or false. These are not interchangeable labels: Java checks the types at compile time. The literal 3 is a number, while the quoted literal "3" is text. A boolean uses true or false without quotes. Notice the capital S in String and the lowercase primitive type names.
Read each declaration aloud before running: customerName is text starting as Mina; quantity is a whole number starting as three. Then match each name to its output line. Change the name value to Sami and the quantity to 4. Predict which two lines change and which two remain identical. Types, ranges, and numeric precision receive their own lesson next.
Main.java · Give each value a meaningful name
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Customer: Mina
Quantity: 3
Weight (kg): 1.5
Ready: false
Initialize a local variable before you use it
A local variable is declared inside a method or another local block. All the variables in these examples are local to main. You can declare a local variable without immediately giving it a value, but Java must be able to establish that it has been assigned before you read it. Merely writing int quantity; does not give this local variable a usable zero.
In this example, the separate assignment quantity = 3; supplies the first value before println reads it. The later assignment quantity = 5; replaces that value. You write the type when declaring the variable, not every time you update it. A second int quantity declaration in the same block would try to create a duplicate local name, not update the original.
Try removing only the first assignment. The first println will now read an uninitialized local, so compilation fails even though a later line assigns 5. Repair the order instead of guessing that Java will fill in a value. Fields and array elements have different initialization rules; do not apply those rules to these local variables.
Main.java · Declare first, initialize before reading
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Starting quantity: 3
Updated quantity: 5
Assignment means store the result, not solve an equation
In Java, a single equals sign performs assignment. Evaluate the expression on its right, then store that result in the variable on its left. So quantity = quantity + 2; reads the old quantity, adds two, and replaces the old value with the result. It is an instruction executed at that moment, not a mathematical claim that a number equals itself plus two.
Trace the example in order: the declaration stores 3, the first update stores 5, and the second update stores 4. Each println reads the value that exists at its own point in the execution. Previously printed text is not changed when the variable changes. Rerunning this complete program starts again from its initial declaration; it does not continue from the previous run's final quantity.
For an int quantity, quantity += 2; is a convenient shorthand for this simple addition update. We use the longer form here so the read-calculate-store sequence stays visible. A single = assigns; == compares values in suitable expressions. We will study comparisons and other operators later. For now, change the added amount and trace all three values before running.
Main.java · Follow one changing quantity
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Start: 3
After adding: 5
After removing: 4
Check your trace after changing the added amount to 4
The lines become Start: 3, After adding: 7, and After removing: 6. The second update reads the result of the first update, not the initial value. Reset restores the starter source so you can repeat the original trace.
Copying and calculating do not create live links
The declaration int originalQuantity = quantity; copies the current primitive value. Both variables initially hold 3, but they are separate variables. Assigning 4 to quantity does not change originalQuantity. The name originalQuantity helps explain why retaining the older value is intentional rather than a forgotten update.
The same timing rule applies to calculations. When Java initializes subtotalCents, it multiplies the quantity available at that moment by 1250 and stores 3750. It does not keep a spreadsheet-style formula attached to subtotalCents. Changing quantity to 4 leaves that subtotal unchanged until the multiplication executes again.
The final assignment explicitly recalculates the subtotal, producing 5000. Pause before that line and predict all three stored values: quantity is 4, originalQuantity is 3, and subtotalCents is still 3750. A program can compile and print plausible numbers while using an outdated calculation. Check the order of updates, not only the arithmetic expression.
Main.java · A calculation is a snapshot, not a live formula
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Quantity now: 4
Original quantity: 3
Previous subtotal (cents): 3750
Recalculated subtotal (cents): 5000
Use final for a binding that must not be reassigned
The final modifier allows a variable to be assigned only once. Here, UNIT_PRICE_CENTS is a fixed unit price for this example, while quantity is allowed to change. Trying to assign a second price to UNIT_PRICE_CENTS produces a compiler error. Making a rule visible in the declaration is stronger than a comment asking future readers not to change it.
Constant-style names conventionally use uppercase words separated by underscores. Ordinary local variables use lower camel case, such as subtotalCents. Uppercase spelling itself does not stop reassignment; final does. Not every final variable needs a constant-style name: a final local customerName can still use camel case when it is simply a one-time binding for that run.
Be precise about the word constant. Java's formal constant variables are final primitive or String variables initialized with constant expressions. This literal price qualifies, but not every final variable does. Also, final on an object reference prevents replacing that reference; it does not generally freeze the referenced object's contents. You will see mutable objects later. Here, final protects the price binding, not the basket quantity or a permanently saved business setting.
Main.java · Protect a fixed price from reassignment
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Unit price (cents): 1250
Subtotal (cents): 2500
New subtotal (cents): 3750
Choose names that explain meaning and respect their scope
Prefer quantity, customerName, and subtotalCents to q, text1, and result. Including cents in a money variable's name makes the unit clear. Names are case-sensitive, so quantity and Quantity are different names. For these beginner examples, start names with a letter, use letters and digits as needed, and avoid spaces, hyphens, and reserved keywords such as class or int.
A local name is usable only within its scope. The extra braces below create a small nested block for demonstration. addedItems is declared inside it and can be read only after its declaration within that block. quantity is declared in the outer block, so it can be read and updated inside the nested block and remains usable afterward.
Try printing addedItems after the closing brace of the inner block. Java cannot resolve that name there. If the value genuinely belongs to the later work, declare it in an appropriate enclosing scope; do not automatically turn every local into a field. Keep variables close to their first useful initialization so readers do not have to search far to understand them.
Main.java · A local name belongs to its block
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Added inside block: 2
Quantity outside block: 5
Optional: var infers a local type; it does not remove the type
With a suitable local initializer, var asks the compiler to infer the type. In var quantity = 3;, the inferred type is int. The example can later assign another int such as 4, but assigning text such as "four" does not change its type and will fail compilation. Java remains statically typed when you use var.
A var local needs an initializer from which the compiler can determine a type. You cannot use var quantity; or initialize it with only null. var is not a general replacement for every type declaration: it is not used to declare fields, method return types, or ordinary method parameters. Our Java 21 baseline supports this feature without preview options.
Explicit types are a useful learning tool and will be used in the basket lab. Choose var later when the initializer already makes the type easy to see. Neither explicit spelling nor inference makes a changing variable final; reassignment rules are a separate decision. Try replacing the example's inferred declarations with int and String and check that the output stays the same.
Main.java · var infers a type once
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Customer: Sami
Quantity: 4
Repair a compiler error, then a stale total
The summary should show Quantity: 4 and Subtotal (cents): 5000. Run the starter. First fix the uninitialized local without changing the fixed unit price. Then look for a subtotal calculated too early: compilation success alone is not the goal.
Main.java · Repair the basket
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Reveal the explained repair
Initializing quantity to 3 fixes the compiler error, but leaving the subtotal before the quantity update would print an outdated 3750. Move the subtotal calculation after the update, or recalculate after it. The solution retains the initial value to make the change visible; if no earlier state is needed, initializing directly to 4 is simpler. Do not change the unit price to compensate for a stale total.
Main.java · Repaired basket
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Quantity: 4
Subtotal (cents): 5000
Independent lab: the changing shopping basket
Build a small basket summary for Mina. Start with three items, then remove one before calculating the amount due. This is a local calculation exercise, not a checkout or saved order. All money values are whole cents to avoid introducing floating-point rounding into this lesson.
- Declare customerName as String with the value Mina and quantity as int starting at 3.
- Declare final int UNIT_PRICE_CENTS as 1250 and final int SHIPPING_CENTS as 300.
- Store the starting quantity in originalQuantity, then remove one item using assignment.
- After the quantity changes, calculate subtotalCents as quantity times the unit price, then totalCents as subtotal plus shipping.
- Print the five labelled lines shown below using the variables, not hard-coded answers.
- Keep the fixed prices unchanged and use a comment to explain the cents convention. Test a different starting quantity.
Use this output contract to check your work:
Customer: Mina
Starting quantity: 3
Final quantity: 2
Subtotal (cents): 2500
Total (cents): 2800
Main.java · Build your basket summary
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Show hints without revealing the solution
Declare the fixed prices first. Copy quantity into originalQuantity before subtracting one. Only then calculate subtotalCents and totalCents. In each println, join a label to a named value. If the numbers look old, inspect the order of the calculations.
Reveal the explained lab solution
Main.java · Basket summary solution
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
originalQuantity stores the starting value 3; changing quantity does not change that copy. Subtotal uses the updated quantity 2, giving 2500 cents. Adding 300 cents shipping gives 2800 cents. The constants name fixed assumptions, while the variables describe this basket. A real basket must also validate quantities, define empty-basket shipping rules, and guard numeric ranges; this exercise deliberately uses small valid fixed values.
Test changes and boundaries
Change only one starting value per run. Reset between experiments so you know which edit caused the difference.
- Start at 4 items: starting quantity 4, final quantity 3, subtotal 3750, total 4050.
- Change Mina to Sami: only the customer line should change.
- Start at 1 item: final quantity 0, subtotal 0, total 300 under this exercise's fixed shipping rule. Do not assume that is a real shop's rule.
- Start at 0 items: the calculation gives -1 item, subtotal -1250, total -950. A well-typed int is not automatically a valid basket quantity. We will add validation with conditions later.
Common mistakes and how to reason about them
Separate a compiler diagnostic from a wrong result. Types and initialization can stop compilation; a calculation in the wrong order can compile perfectly. Read the first useful diagnostic, make one focused change, and run again.
variable quantity might not have been initialized
A local is being read before Java can establish it has a value. Find the first read, then initialize it meaningfully before that line. Adding a later assignment cannot repair an earlier read.
incompatible types
Check the declared type and the assigned expression. The text "3" is not an int; a number and its printed representation are different values. Do not add a cast at random. Decide whether you intend a numeric count or text.
variable quantity is already defined
You probably wrote the type again when intending to update an existing local. Declare it once, then assign to its name. Declaring a local with the same name in an overlapping nested local scope is not a workaround.
cannot assign a value to final variable
A final binding has already received its value. If the value should genuinely change, reconsider whether final fits its role. If it represents a fixed price, update the quantity or calculated total instead of weakening the fixed-price rule.
cannot find symbol
Look for a spelling or capitalization mismatch, use before declaration, or a name declared inside a block that has ended. Align the name and scope with the intended use; do not create a second unrelated variable merely to silence the message.
The code runs, but the total is old
A stored calculation does not re-run when an input variable changes. Trace the assignments from top to bottom. Calculate after the final input change, or deliberately recalculate when you need an updated result.
Frequently asked questions
Does a variable remember its value between Run clicks?
Not in these programs. Each run starts a new execution, and main initializes its locals again. The editor may remember your source, but that is different from the program saving basket state.
Can I change a variable's type after declaring it?
No. Its declared or inferred type remains fixed. You can assign another compatible value, but an int variable cannot become a String variable. Use a separate clearly named variable when you need a different representation.
Does final mean the value must be known when I write the code?
No. A final local can receive a value computed at runtime, or be declared and assigned once later before use. It cannot be reassigned afterward. Only some final primitive or String variables meet Java's narrower definition of a constant variable.
Why use cents instead of double for the basket?
Whole cents keep this small exercise's arithmetic exact and its units explicit. double is useful for approximate measurements but cannot exactly represent many decimal fractions. Real pricing needs deliberate rounding, range, tax, and currency rules; choosing int alone does not solve all money problems.
Does final make an object immutable?
No. It prevents a second assignment to that variable. A referenced object may still allow changes through its methods or elements. String objects are immutable because of String's own design, not because a variable referring to one is final.
Name the value, trace the changes, check the result
A declaration introduces a typed name. Initialization gives it its first value; assignment can replace it when the binding is not final. Local values must be initialized before a read. Copies of primitive values and calculated totals do not stay linked to their inputs.
Before moving on, explain why the basket keeps an original quantity, why the prices are final, and why the subtotal is calculated after removing an item. Next is Java Data Types: choosing appropriate representations and understanding their limits.
Can you follow the values?
Answer all six questions and read the reasoning. Quiz results are temporary on this page and do not save course progress.
References and related learning
The basket examples, explanations, and practice tasks are original SovranCode material. These official Java references support the language rules.
- dev.java: variables and naming
- Java 21 specification: variables, final, and initial values
- Java 21 specification: local variable declarations and var
- Java 21 specification: scope of a declaration
Review output and comments · Review Java syntax · Java course roadmap.
Last updated: