Variables in Java
Variables in Java are classified into primitive and reference variables. From the programmer's perspective, a primitive variable stores its value directly, whereas a reference variable holds a reference (address) to the actual object. Reference variables are practically always used to refer to objects in Java. Let's look at both types with the help of examples.
Two Types of Variables
1. Primitive variable
Used to represent primitive values, as shown below:
/*
int x = 10;
byte b = 20;
short a = 30;
char c = 'a';
*/
2. Reference variable
Used to refer to objects, for example:
/*
Student s = new Student();
*/
Based on the position of declaration and behavior, all variables are divided into three types:
- Instance variables
- Static variables
- Local variables
Instance Variable
If the value of a variable varies from object to object, it's called an instance variable. Instance variables should be declared within the class directly, but outside of any method, block, or constructor.
Example:
/*
class Test{
String name;
int x = 20;
} // is valid
*/
Here, name and x are instance-level variables, and any object created from Test gets its own copy of them.
/*
class Test{
Test(){
String a; // not valid, this is a constructor — a is a local variable here
int x; // not valid — local variable
}
void m(){
String s; // not valid — local variable
int x = 20; // not valid — local variable
}
}
*/
Case 1: For every object, a separate copy of the instance variable will be created.
Case 2: Instance variables are created when the object is created and destroyed when the object is destroyed; hence the scope of an instance variable is the same as the scope of the object.
Case 3: We can't access instance variables directly from a static area — we can only access them through an object reference. However, we can access instance variables directly from the instance area.
Example:
/*
class Test{
int x = 20;
public static void main(String[] args){
System.out.print(x); // compile-time error
Test t = new Test();
System.out.print(t.x); // valid, prints 20
}
public void m(){
System.out.print(x); // valid, prints 20
}
}
*/
Case 4: For instance variables, the JVM provides default values, so we're not required to perform initialization explicitly.
Example:
/*
class Test{
int x;
double d;
boolean b;
String s;
public static void main(String[] args){
Test t = new Test();
System.out.print(t.x); // 0
System.out.print(t.d); // 0.0
System.out.print(t.b); // false
System.out.print(t.s); // null
}
}
*/
Note: Instance variables are stored in heap memory as part of the object.
Note: Instance variables are also known as object-level variables or attributes.
- Instance variables are also known as object-level variables or attributes.
- A separate copy of an instance variable is created for every object.
Static Variable
We declare a static variable at the class level by using the static modifier.
Unlike instance variables, where a separate copy is created for every object, a single copy of a static variable is created and shared by every object of the class.
Static variables should be declared within the class directly, but outside of any method or constructor.
- Static variables are created when the class is loaded and destroyed when the class is unloaded; hence the scope of a static variable is exactly the same as that of the class file.
- We can access static variables either through an object reference or the class name, but using the class name is recommended.
- Within the same class, using the class name is not required — we can access it directly.
- We can access static variables directly from both instance and static areas.
- For static variables, the JVM provides default values, so we're not required to perform initialization explicitly.
- Static variables are also known as class-level variables or fields.
Example — how to access a static variable:
/*
class Test{
static int x = 10;
public static void main(String[] args){
Test t = new Test();
System.out.print(t.x);
System.out.print(Test.x);
System.out.print(x);
}
public void m(){
System.out.print(x);
}
}
*/
Example — default value for a static variable:
/*
class Test{
static int x;
static double y;
static String s;
public static void main(String[] args){
System.out.print(x); // 0
System.out.print(y); // 0.0
System.out.print(s); // null
}
}
*/
Process for loading and destroying a static variable:
[diagram image goes here]Instance variable
- Instance variables are also known as object-level variables or attributes.
- A separate copy of an instance variable is created for every object.
Static variable
- Static variables are also known as class-level variables or fields.
- A single copy of a static variable is created and shared by every object.
Local Variable
Sometimes, to meet a programmer's temporary requirements, we can declare variables inside a method, block, or constructor. Such variables are called local variables, temporary variables, stack variables, or automatic variables.
[diagram image goes here]Note: Local variables are stored in stack memory.
- A local variable is created when the block in which it's declared starts executing.
- Once the block's execution completes, the local variable is automatically destroyed; hence its scope is limited to the block in which it was declared.
- Local variables are also called thread-safe.
- For local variables, the JVM does not provide default values — we must initialize them explicitly before use.
Example:
/*
class Test{
public static void main(String[] args){
int x;
System.out.print(x);
}
}
// error: variable x might not have been initialized
*/
Case 1: Before using a variable, it is required to perform initialization.
/*
class Test{
public static void main(String[] args){
int x;
System.out.print("Hello");
}
}
*/
/*
class Test{
public static void main(String[] args){
int x;
if(args.length > 0){
x = 20;
}
System.out.print(x);
}
}
*/
I got a compile-time error: variable x might not have been initialized.
Case 2: The only applicable modifier for a local variable is final. If we mistakenly try to apply any other modifier, we'll get a compile-time error.
Example:
/*
class Test{
public static void main(String[] args){
public int x = 20;
private int x = 20;
protected int x = 20;
static int x = 20;
transient int x = 20;
volatile int x = 20;
// all of the above are invalid — compile-time error: illegal start of expression
final int x = 20; // valid
int x = 20; // valid
}
}
*/
Case 3: If we don't declare a variable with any access modifier, it gets default (package-private) access — but this rule applies only to instance and static variables, not to local variables.
Conclusion
For instance and static variables, the JVM provides default values, so we're not required to initialize them explicitly.
But for local variables, the JVM does not provide default values — we must initialize them explicitly before using them.
Instance and static variables can be accessed by multiple threads simultaneously, so they are not thread-safe. In the case of local variables, a separate copy is created for every thread, so local variables are thread-safe.
[diagram image goes here]Every variable in Java is either instance, static, or local.
Every variable in Java is either primitive or reference.
Hence, the various possible combinations of variables in Java are as shown below:
Uninitialized Array
/*
class Test{
int[] x;
int[] y = new int[2];
static int[] s;
static int[] ss = new int[3];
public static void main(String[] args){
Test t = new Test();
System.out.print(t.x); // null
System.out.print(t.x[0]); // runtime exception: NullPointerException
System.out.print(t.y); // [I@8sddf
System.out.print(t.y[0]); // 0
System.out.print(s); // null
System.out.print(s[0]); // runtime exception: NullPointerException
System.out.print(ss); // [I@9dfdddfd
System.out.print(ss[0]); // 0
}
}
*/
0 Comments