This article provides a complete overview of Java variables, covering everything from basic concepts to modern features like local variable type inference var
. It explores variable types, declaration, initialization, scope, lifetime, and naming conventions. Whether you're preparing for an interview or seeking a quick refresher, this guide provides essential insights.
Table of Contents
Java classes have two primary elements: methods, often called functions or procedures in other languages, and fields, more generally known as variables. Together these are called the members of the class. Variables hold the state of the program, and methods operate on that state. Other building blocks include interfaces. So, variables are essentially data members within a class.
1. What is a Variable?
In Java, a variable is a named storage location that holds a value. Think of it as a container with a label (the variable name) where you can store data. Variables are essential for storing, retrieving, and manipulating information during program execution. Each variable has a specific data type (e.g., int
, String
, boolean
) that determines the kind of values it can hold. Variables are the building blocks for storing and processing information.
Variable Types
In Java, variables are categorized into two main types: primitive and reference types. For a detailed explanation of these types, refer to previous article. There you will find a brief overview of each type and their key differences.
Declaring and Initializing Variables
When you declare a variable, you associate its name with a specific data type.
String name;
int number;
After a variable's declaration, it can be assigned a value, a process known as initialization.
name = "The Best Zoo";
number = 100;
Below, the previous declarations and initializations are merged into concise code:
String name = "The Best Zoo";
int number = 100;
Declaring Multiple Variables: you can declare many variables in the same declaration as long as they are all of the same type.
void sandFence() {
String s1, s2; // declared but not yet initialized
String s3 = "yes", s4 = "no"; // initialized variables
}
void paintFence() {
int i1, i2, i3 = 0; // variable 'i3' is initialized
}
There are three variables: i1
, i2
(are declared), and i3
(is initialized).
int num, String value; // DOES NOT COMPILE
This code doesn’t compile because it tries to declare multiple variables of different types in the same statement.
Here are a few ways to summarize those variable declaration examples, presented in a more informative style:
int i1, i2, i3 = 0; // all declared; 'i3' is initialized
int num, String value; // DOES NOT COMPILE: different types
boolean b1, b2;
String s1 = "1", s2;
double d1, double d2; // DOES NOT COMPILE
int i1; int i2;
int i3; i4; // DOES NOT COMPILE
Naming Conventions and Legal Identifiers for Variables
An identifier is the name of a variable, method, class, interface, or package.
- identifiers may begin with a letter, a
$
symbol, or a_
symbol. - identifiers can include numbers but not start with them.
- since Java 9, a single underscore
_
is not allowed as an identifier. - you cannot use the same name as a Java-reserved word.
- the first character is not allowed to be a number, and reserved words are not allowed.
A reserved word is a special keyword that Java uses for specific purposes, so you are not allowed to use it. Remember that Java is case-sensitive, so you can use versions of the keywords that only differ in case.
abstract | assert | boolean | break | byte | case | catch |
char | class | const | continue | default | do | double |
else | enum | extends | false | final | finally | float |
for | goto | if | import | instanceof | int | interface |
long | implements | native | new | null | package | private |
protected | public | return | short | static | strictfp | super |
switch | synchronized | this | throw | throws | transient | true |
try | void | volatile | while | _ (underscore) |
❗Note: In this table, bold text indicates reserved keywords (like const
and goto
) that are not currently used in Java but are still restricted to avoid potential conflicts with other languages. And highlighted terms (like true
, false
, and null
) aren’t actually reserved words, but literal values, which are also prohibited as identifiers and are listed here for clarity.
To solidify understanding of identifier rules, consider these examples:
Legal Identifiers:
long okidentifier;
float $OK2Identifier;
boolean _alsoOK1d3ntifi3r;
char __SStillOkbutKnotsonice$;
Illegal Identifiers:
int 3DPointClass; // identifiers cannot begin with a number
byte hollywood@vine; // @ is not a letter, digit, $ or _
String *$coffee; // * is not a letter, digit, $ or _
double public; // public is a reserved word
short _; // a single underscore is not allowed
Beyond the rules for legal identifiers, following consistent naming conventions is crucial for code readability and maintainability.
Style: camelCase
While Java technically allows different styles, the development community largely adheres to camelCase, the preferred style for most Java identifiers. In camelCase:
-
method and variable names are written with the first letter being lowercase, capitalizing subsequent words (e.g.,
calculateTotal
,userFirstName
). -
class and interface names are written with the first letter being uppercase, capitalizing subsequent words (e.g.,
CustomerService
,Printable
). Note: Avoid starting class names with$
, as the compiler uses this symbol for internal files.
Style: snake_case
While syntactically valid, snake_case is generally discouraged for variable and method names in Java. However, there are some common exceptions:
-
static
final
constants are commonly written in uppercase snake_case (e.g.,THIS_IS_A_CONSTANT
). -
enum values tend to be written in uppercase snake_case for consistency and readability, as in
Color.RED
,Color.DARK_GRAY
, and so on.
2. Variable Scope and Lifetime
In Java, variables have a scope that determines where they can be accessed in your code, and a lifetime that dictates how long they exist. Java defines three primary types of variables based on these characteristics: class variables, instance variables, and local variables.
2.1. Class Variables (Static Fields)
You can define a static field using the static
keyword. You do not need an instance of the class to access static fields. You can access static class fields by writing the class name before the field. There is only one copy of a static variable, no matter how many instances of the class there are.
2.2. Instance Variables (Non-Static Fields)
Instance variables in Java are variables declared within a class without the static
keyword, outside of any method. Such a variable is associated with a specific instance of a class, and the value of the variable in one instance does not affect the value of the same variable in another instance of this class.
Default initialization values by type: Class and Instance variables do not require initialization, they are automatically initialized to default values. As soon as you declare them, they receive default values: null
for objects and 0
/ false
for primitives.
boolean
-> false
byte
, short
, int
-> 0
long
-> 0L
double
-> 0.0
float
-> 0.0f
char
-> '\u0000'
(NULL)
All object references (everything else) -> null
2.3. Local Variables
This is a variable defined within a method (also method parameters or constructor parameters) and cannot be used outside the method. Local variables must be initialized before use (it’s ok to have an uninitialized local variable as long as you never use it). They do not have default values and contain garbage data until initialized.
public void findAnswer(boolean check) {
int answer;
int onlyOneBranch;
if (check) {
onlyOneBranch = 1;
answer = 1;
} else {
answer = 2;
}
System.out.println(answer);
System.out.println(onlyOneBranch); // DOES NOT COMPILE
}
In the method, the variable answer
is guaranteed to be initialized before it is used, so the code compiles successfully. However, the variable onlyOneBranch
is only initialized if the check is true
. If a check is false
, onlyOneBranch
remains uninitialized, leading to a compile error when trying to print it. So, the compiler knows the check can also be false
, resulting in uninitialized code and giving a compiler error.
public void findAnswer(boolean check) { }
public void checkAnswer() {
boolean value;
findAnswer(value); // DOES NOT COMPILE
}
The call to findAnswer()
does not compile because it tries to use a local variable that is not initialized.
The scope and lifetime of a Java variable are intrinsically linked to its type and where it is declared.
- Local variable: scope extends from the point of declaration to the end of the enclosing block.
- Instance variable: available from the point of declaration until the object is garbage collected.
- Class variable: available from the moment of declaration until the program terminates.
3. Local Variable Type Inference (var)
Starting in Java 10, you can use the keyword var
instead of the type for local variables under certain conditions. To use this feature, you just type var
instead of the primitive or reference type.
public void whatTypeAmI() {
var name = "Hello";
var size = 7;
}
The formal name of this feature is local variable type inference. This means that it is used only as a local variable. It cannot be used as a static var
(class or local):
public class VarKeyword {
var tricky = "Hello"; // DOES NOT COMPILE: instance var
static var h = "String"; // DOES NOT COMPILE: class var
public void whatTypeAmI() {
static var size = 7; // DOES NOT COMPILE: static local
}
}
In Java, var
is still a specific type defined at compile time. It does not change type at runtime.
public void reassignment() {
var number = 7;
number = 4;
number = "five"; // DOES NOT COMPILE
}
To better understand how var
works and where it can be used, let's look at some practical code snippets.
int a, var b = 3; // DOES NOT COMPILE
var a = 2, b = 3; // DOES NOT COMPILE
All the types declared on a single line must be the same type and share the same declaration. Java does not allow var
in multiple variable declarations.
var n = null; // DOES NOT COMPILE
The compiler is prompted to define the null
type. It can be any type of reference. The only choice the compiler can make is an Object
. Java developers have decided that it is better not to allow var
for null
than to guess about intentions.
While a var
cannot be initialized with a null
value without a type, it can be assigned a null
value after it is declared, provided that the underlying data type of the var
is an object.
var n = "myData";
n = null;
var m = 4;
m = null; // DOES NOT COMPILE: primitives are not assigned a null
The n
is of type String
, which is an object that compiles without issue. But since the type of m
is a primitive int
, it cannot be assigned a null
value that does not compile.
var o = (String) null;
By the way, a var
can be initialized to a null
value if the type is specified.
public int addition(var a, var b) { // DOES NOT COMPILE
return a + b;
}
Also, it can’t be used as method parameters. Since, the a
and b
are method parameters. These are not local variables.
While var
is not a reserved word and is allowed to be used as an identifier, it is considered a reserved type name. Naming a local variable var is legal. The following examples illustrate this:
package var;
public class Var {
public void var() {
var var = "var";
}
public void Var() {
Var var = new Var();
}
}
A reserved type name means it cannot be used to define a type, such as a class, interface, or enum.
public class var { // DOES NOT COMPILE
public var() { }
}
Summarizing the use of var
, let's consider the key rules.
What you can do with var
:
- A
var
can be used as a local variable in a constructor, method, or initializer block. - The value of a
var
can change, but the type cannot.
What you cannot do with var
:
- A
var
cannot be used as a parameter in a constructor and method, instance variables, or class variables. - A
var
must always be initialized on the same line (or statement) where it is declared. - A
var
cannot be initialized with anull
value without a type. - A
var
is not permitted in a multiple-variable declaration. - A
var
is a reserved type name but not a reserved word, meaning it can be used as an identifier except as a class, interface, or enum name.