Java
July 11, 2020Variables in Java can be categorized into instance, static & local. In programming, it is always advisable to only declare and initialize a variable right before it’s usage. If a value to initialize couldn’t be identified, the need of the variable should be re-evaluated. This is to avoid unnecessary memory usage and enhance code readability because of the reduced scope. In Java, out of these 3 variables, only one is required to be initialized before it’s usage or else compiler would throw an error. In other words, local variables don’t have default values. Below is a table of different types and their default values. Here, reference types include the wrappers of the primitive types.
Type | Default Value |
---|---|
byte , short , int , long |
0 |
float , double |
0.0 |
char |
\u0000 |
boolean |
false |
Reference Type | null |
Before looking into this behaviour of the compiler, it is necessary to understand what these variables are and how they differ from each other.
Static Variables
Static variables (or Class variables) are global variables that are available to all programs on the running JVM instance. These are declared on classes or interface with the keyword static
. They can be accessed using dot .
operator using the class/interface name. Below are their features,
- Loaded into memory when the class gets loaded even before an object of the class is created
- Don’t participate in garbage collection
These variables can be left uninitialized after declaration and they’re assigned with their respective default value. If a static
variable is declared final
, it wouldn’t take the default value. It must be initialized either during declaration or it can be initialized in a special block in class called Static Initializer. A non-final static variable can be used/modified anywhere.
Instance Variables
Java is an object oriented programming language. Everything in java is enclosed within a class. A class has properties and can perform actions. The properties are called Instance Variables. An instance variable is unique for every object created. They can be accessed using dot .
operator using the object name. Below are their features,
- Participate in garbage collection once they go out of scope
- Scope is within the object and cannot be accessed outside of it.
- Can only be accessed/modified inside a non-static method
These variables can also be left uninitialized similar to static variables and they’re auto initialized to the default values. If an instance variable is declared final
, it must be either initialized during declaration or on the constructor or on a special block called Instance Initializer.
Local Variables
Local variables are the ones that are declared inside a method. They must be initialized to some value failing which compiler would throw an error. Scope of a local variable is within the method and it can’t accessed outside of it. These variables live on the stack and get popped once the method call ends. For reference types, the object it refers to lives on the heap whereas the type on the stack.
Below code example shows the behaviour of static, local and instance variable.
public class Variable{
public static String staticVariable;
private final int instanceVariable;
public boolean defaultInstanceVariable;
// Static Initializer Block
static {
System.out.println("Static Initializer Block");
staticVariable= "Static Variable Example";
System.out.printf("staticVariable After Initialization = %s\n",staticVariable);
}
// Instance Initializer Block
{
System.out.println("Instance Initializer Block");
instanceVariable= 1;
System.out.printf("instanceVariable After Initialization = %d\n",instanceVariable);
}
// Constructor Block
public Variable(){
System.out.println("Constructor Block");
System.out.printf("defaultInstanceVariable = %b\n",defaultInstanceVariable);
}
// Static Method
public static void staticMethod(){
System.out.println("Static Method");
}
// Instance Method
public void instanceMethod(){
char localVariable = '!';
System.out.println("Instance Method");
System.out.printf("localVariable After Initialization = %c\n",localVariable );
}
}
//Call 1:
new Variable().instanceMethod();
//Output 1:
/**
Static Initializer Block
staticVariable After Initialization = Static Variable Example
Instance Initializer Block
instanceVariable After Initialization = 1
Constructor Block
Instance Method
localVariable After Initialization = !
**/
//Call 2:
Variable.staticMethod();
//Output 2:
/**
Static Initializer Block
staticVariable After Initialization = Static Variable Example
Static Method
**/
Why only local variables?
In Java, only local variables have a very limited (method) scope and lifetime. And they have a predictable execution route that the compiler understands. These variables don’t go beyond the method. Compiler can identify where the variable is declared and can very efficiently instruct a programmer to initialize a variable before using it. When a variable is used without initialization, there’s a possibility for a potential bug in the program. Also, initializing every variable with a default value takes a hit on the performance. It is actually an assist from the compiler to make the program better. The actual question should be, why not the compiler helps in not using a static/instance variable before initialization?
The answer to that question lies in the complexity or the more number of ways in accessing those variables. When it comes to a method, the execution path is very clear. The compiler can very well trace the route from using the variable back to its declaration. There’s no unique flow that the compiler can identify for a static/instance variable to be set with a value. The initialization can happen under a different program altogether and the usage can be of some place else. Since there’s no definite path and the path to map is not a narrow line, they’re provided with default values. A default value is definitely better than an unsure/random value. If those variables are not initialized, they can have any value on them and that can be from irrelevant data to sensitive data.
🔥