Java Static Variables — Race Condition in Trade Counter
Duplicate sequence numbers and fluctuating trade counts from unsynchronized static variables.
- Variables are named memory slots with a type and value
- Constants use
finalkeyword and SCREAMING_SNAKE_CASE - Local variables must be initialized before use; instance/static get defaults
- Java has 8 primitive types plus reference types for objects
- Use
finalfor values that must never change — compiler enforces it - Uninitialized local variables cause a compile-time error
Think of a variable like a labelled box in your bedroom. You write a name on the outside — say 'socks' — and you can put things in, take them out, or swap the contents whenever you like. A constant is like a box that's been padlocked shut the moment you fill it — the label says 'date of birth' and nothing can ever change what's inside. Java works exactly the same way: variables hold data that can change, constants hold data that must never change.
Every program you have ever used — a weather app, a video game, a banking website — is constantly juggling data. A temperature reading, a player's score, a bank balance: all of it has to live somewhere in memory while the program is running. Without a way to name and store that data, writing even the simplest program would be impossible. Variables are the fundamental building blocks that make this work, and they show up in literally every Java file ever written.
Before variables existed, early programmers had to reference raw memory addresses — imagine telling someone to 'grab the thing at shelf 0x3F4A' instead of just saying 'grab the sugar'. Variables solve this by letting you give meaningful names to memory locations, so your code reads like English instead of a hardware manual. Constants take this one step further by letting you shout 'this value must NEVER change' — which prevents bugs that are notoriously hard to track down.
By the end of this article you'll know how to declare every kind of variable Java supports, understand the difference between primitive and reference types, lock down values with the final keyword, name things in a way that won't embarrass you in a code review, and dodge the three most common mistakes beginners make on day one.
What a Variable Actually Is — Memory, Names and Types
When your Java program runs, the operating system hands it a chunk of RAM to work with. A variable is just a named slot inside that RAM. You tell Java three things when you create one: what type of data it will hold, what you want to call it, and optionally what value to put in it right away.
The type matters because Java needs to know how much memory to reserve. A single character takes up far less space than a decimal number with ten digits. Java's 'primitive types' are the basic building blocks — whole numbers, decimal numbers, single characters, and true/false values. Think of them as different sized boxes in your warehouse.
Every variable has a lifecycle. It comes into existence when you declare it, holds whatever value you give it, and is destroyed when the block of code it lives in finishes running. Understanding this — called scope — will save you hours of debugging later.
You can declare a variable without giving it a value (declaration only), or declare it and give it a value at the same time (declaration + initialization). Both are valid, but Java will refuse to let you use a local variable before it's been given a value — it's stricter than most languages and that strictness is actually a gift.
Variable Naming Rules and the Conventions That Get You Hired
Java has hard rules — break them and the code won't compile. Then there are conventions — break those and senior developers will wince during your code review.
The hard rules: A variable name must start with a letter, underscore _, or dollar sign $. It cannot start with a number. It cannot be a Java keyword like int, class, or return. Names are case-sensitive, so playerScore and playerscore are two completely different variables.
The convention: camelCase. Java developers universally use camelCase for variable names — start with a lowercase letter, then capitalize the first letter of every subsequent word. So accountBalance, numberOfLives, isEmailVerified. This isn't enforced by the compiler, but deviating from it signals immediately that you're new to the language.
Name for meaning, not brevity. A variable called n tells the next developer nothing. A variable called numberOfActiveUsers tells them everything. Yes, it's more typing. The five seconds you save typing a short name costs the next person (often future-you) five minutes of head-scratching.
Avoid abbreviations unless they're universally understood (url, id, html are fine). Avoid names that include the type, like intPlayerAge — that's a relic from the 1990s called Hungarian notation and it's considered noise in modern Java.
temp in a critical financial calculation masked a bug for three sprints.n is never acceptable.Constants With `final` — Locking Down Values That Must Never Change
Some values in your program should never change after they're set. The number of days in a week. The value of Pi. Your application's maximum upload size. The tax rate for a given region. If these values could accidentally be overwritten, bugs would be catastrophic — imagine a banking app where the interest rate could be silently changed mid-calculation.
Java's answer is the final keyword. Put final before a variable declaration and Java will throw a compile error the moment anyone tries to reassign it. The value is locked in for the lifetime of the program. These are called constants.
By convention, constant names use SCREAMING_SNAKE_CASE — all uppercase letters with underscores separating words. This visual distinction means any developer who reads MAX_LOGIN_ATTEMPTS instantly knows 'this value never changes', without having to scroll up to check the declaration.
You'll most often see constants declared with both static and final at the class level. static means the constant belongs to the class itself rather than to any one object — so there's only ever one copy of it in memory, shared everywhere. For now, just know that static final is the standard idiom for class-level constants and you'll see it constantly in production code.
final on a primitive locks the value permanently. But final on an object (like an ArrayList) only locks the reference — the object itself can still be modified. So a final List can still have items added to it. This trips up even intermediate developers. If you want a truly immutable object, that's a separate discussion involving immutable classes.final reference to a mutable object does not make the object immutable.static final for constants reduces memory footprint — one per class instead of per instance.final prevents reassignment — not mutation.final with static for class-level constants.Variable Initialization: Default Values, Local vs Instance, and the 'var' Keyword
One of the most common sources of confusion is when variables get their first value. Java applies different rules depending on where a variable is declared.
Local variables — those inside a method, constructor, or block — must be explicitly assigned a value before they are used. The compiler will refuse to compile code that reads from an uninitialised local variable. This is a feature, not a bug: it prevents a whole class of bugs that plague languages like C or JavaScript.
Instance variables (fields) and static variables get default values automatically if you don't set them. Numbers default to 0 (0.0 for floating point), booleans default to false, and any object reference defaults to null. These defaults are often the source of subtle bugs — especially the null default for object references, which leads to NullPointerException at runtime.
Java 10 introduced the var keyword for local variables, allowing type inference. var tells the compiler 'figure out the type from the initialiser.' var count = 10; is equivalent to int count = 10;. But var is not a magic 'any type' — the type is still fixed at compile time, and you cannot reassign a different type. var is only allowed for local variables with an initializer, and using it incorrectly can make code harder to read.
var when the type is obvious from the initialiser, like var list = new ArrayList<String>(). Avoid var when the type is not clear, e.g. var result = someMethod() — it hurts readability. Also never use var for return types or method parameters; that requires var-like features from Java 10 for locals only.var for a method call that returned a Map<String, List<Customer>> — the reader couldn't tell what the variable represented without digging into the method.var only when the type is immediately visible; always initialize local variables explicitly.var only when the type is clear from context.var for brevity.Where Variables Live — Local, Instance and Static Variables Explained
Not all variables are created equal — where you declare a variable determines who can use it, how long it lives, and what its default value is. Java has three distinct categories, and mixing them up is one of the most common sources of early confusion.
Local variables live inside a method. They're born when the method is called and destroyed when it returns. They have no default value — Java demands you initialize them before use, full stop.
Instance variables (also called fields) live inside a class but outside any method. Each object you create from that class gets its own private copy of these variables. They DO get default values: 0 for numbers, false for booleans, null for objects. They live as long as the object lives.
Static variables also live at the class level, but there's only ONE copy shared across every object of that class. Change it in one place and every object sees the new value. They're perfect for things like counting how many objects have been created, or storing shared configuration.
Think of it this way: static variables are like a whiteboard in a shared office (everyone sees the same thing), instance variables are like each person's personal notebook (each person has their own copy), and local variables are like a sticky note you write during a phone call and throw away when you hang up.
The Shared Counter That Crashed a Trading Platform
int is atomic. In Java, count++ is three separate operations: read, add, write — not thread-safe.int tradeCounter = 0 was incremented via tradeCounter++ inside a method called by multiple threads. No synchronisation or atomic class used.int with AtomicInteger and used incrementAndGet(). Alternatively, synchronised the increment method, but AtomicInteger is faster for simple counters.- Never assume single-line operations are atomic in Java.
- Use
AtomicIntegerorsynchronizedfor shared mutable state. - For constants that must be thread-safe, prefer
finalimmutable values.
Key takeaways
final keyword makes a variable a constantstatic at the class level for true shared constants.numberOfActiveUsers not n) is what separates code that gets approved in review from code that gets sent back.Common mistakes to avoid
3 patternsUsing a local variable before initializing it
int totalScore;) but forget to assign it a value before using it in a print or calculation.int totalScore = 0;.Confusing `=` (assignment) with `==` (comparison)
if (playerScore = 100) instead of if (playerScore == 100) is a logic error. In Java, single = assigns a value; double == compares two values. Java will actually catch this specific case and throw a compile error since the result of an assignment isn't a boolean, but understanding the distinction early prevents subtle bugs in languages where this compiles silently.== for equality checks, and = only for assignment. For boolean comparisons, consider using if (condition) directly.Trying to reassign a `final` variable
final int MAX_RETRIES = 3; and then later writing MAX_RETRIES = 5; causes a compile error: 'cannot assign a value to final variable MAX_RETRIES'.final if the value needs to change, or rethink your design — maybe you actually want a regular variable. The error is a feature: it means Java caught your mistake before it became a runtime bug.Interview Questions on This Topic
What is the difference between a variable and a constant in Java, and how do you declare each one?
final keyword. Variables use camelCase naming; constants use SCREAMING_SNAKE_CASE. Example: int age = 30; is a variable; final int MAX_AGE = 120; is a constant. Constants are often declared static final at the class level.Frequently Asked Questions
That's Java Basics. Mark it forged?
6 min read · try the examples if you haven't