23

Why do variables declared in a class have default values, but the variables declared inside methods, said to be "local variables", don't have default values in Java?

For example

class abc
{
   int a;

   public static void main(String ss[])
   {
        int b;

          abc aa=new abc();
          System.out.println(aa.a);
          System.out.println(b);
    }
 }

In this above example variable a has default value of 0 but variable b gives error that it might not have been initialized.

sschuberth
  • 28,386
  • 6
  • 101
  • 146
Shikhil Bhalla
  • 392
  • 1
  • 5
  • 17
  • 14
    `int a` actually has a default value of `0`. – FThompson Aug 14 '13 at 08:13
  • 1
    the whole memory block of the object is always filled with zeroes, thats why all variables in an object default to 0, `b` is a local variable and simply isn't initialized at that part . it get's initialized when a value is assigned – x4rf41 Aug 14 '13 at 08:15
  • 1
    but y b variable dont has default value? – Shikhil Bhalla Aug 14 '13 at 08:15
  • 5
    `b` is allocated in stack, unlike `a`, and that is not zeroed for performance reasons. (or more correctly: implementations are not required to clear it because it would necessarily limit performance of implementations for little gain) – kiheru Aug 14 '13 at 08:17
  • See http://stackoverflow.com/questions/9687634/java-variable-default-value – Robert M. Aug 14 '13 at 08:18
  • 4
    Please use capitalization -- I'm never editing one of *your* posts again – Dexygen Aug 14 '13 at 08:25
  • I've never found a satisfactory "Why" for this. As mentioned above, performance seems to be one reason, but I've not found an actual reference to one of the designers confirming this, or an explanation of why the designers thought "performance" was more important than "consistency". The best explanation I've found says, (1) you need to find one of the original designers or (2) just don't worry about it, it's not that important :-) http://www.coderanch.com/t/579112/java/java/compiler-default-values-local-variables – matt freake Aug 14 '13 at 09:13

4 Answers4

16

All member variable have to load into heap so they have to initialized with default values when an instance of class is created. In case of local variables, they don't get loaded into heap they are stored in stack until they are being used before java 7, so we need to explicitly initialize them. Now the "Java Hotspot Server Compiler" performs "escape analysis" and decides to allocate some variables on the stack instead of the heap.

Ashwani
  • 3,463
  • 1
  • 24
  • 31
  • Local variables loaded into heap? Did you notice the OP is talking about an *int*, which is a primitive type? o.O – Bruno Reis Aug 14 '13 at 08:49
  • He is taking `int` as an example only. – Ashwani Aug 14 '13 at 08:53
  • Still, if you have a local variable `Object o`, the *reference* still lives in the stack, not in the heap. If you don't initialize `o`, it is an error to use it -- the problem is using the *reference* without initialization. If you simply do `o = null`, then you can use it: you have initialized the reference, which, again, lives in the stack (not in the heap) and there's nothing "loaded into the heap" after this initialization. If you do `o = new Object()`, then you have touched the heap, but this alone has nothing to do with the fact that you cannot used uninitialized local variables. – Bruno Reis Aug 14 '13 at 08:56
  • Yes, thats not heap, it is stack. – Ashwani Aug 14 '13 at 08:59
  • So, I'd suggest you fix your answer. Currently, it is misleading. – Bruno Reis Aug 14 '13 at 09:00
  • but before java 7, The local variables were stored on a stack and instance variables are stored on the heap. – Ashwani Aug 14 '13 at 09:13
  • 2
    I think there's a huge misunderstanding here. I'm not talking specifically about Java 7 or about escape analysis. Oh, whatever. I give up on this, and hope people won't get confused. – Bruno Reis Aug 14 '13 at 09:19
  • 2
    'Loaded into stack before they are being used before Java 7' is meaningless, and 'so we need to explicitly initialize them' is a *non sequitur*. There is nothing here that actually answers the question. The first two sentences just restate it, and the remainder is just a lot of confused waffle. The final sentence is irrelevant. @BrunoReis I agree entirely. – user207421 Sep 11 '16 at 01:29
  • This doesn't answer the question. Why would the heap have different rules than the stack? There's no difference between the two that would lead to different rules for uninitialized variables. – John Kugelman Jul 06 '20 at 02:07
2

Local variables Initialization

Variables declared in methods and in blocks are called local variables. Local variable are not initialized when they are created at method invocation. Therefore, a local variable must be initialized explicitly before being used. Otherwise the compiler will flag it as error when the containing method or block is executed.

Example:

public class SomeClassName{

public static void main(String args[]){
int total;
System.out.println("The incremented total is " + total + 3); //(1)
}
}

The compiler complains that the local variable total used in println statement at (1) may not be initialized. Initializing the local variable total before usage solves the problem:

public class SomeClassName{

public static void main(String args[]){
int total = 45; //Local variable initialized with value 45 System.out.println("The incremented total is " + total+ 3); //(1)
}
}

Fields initialization

If no initialization is provided for an instance or static variable, either when declared or in an initializer block, then it is implicitly initialized with the default value of its type. An instance variable is initialized with the default value of its type each time the class is instantiated, that is for every object created from the class. A static variable is initialized with the default value of its type when the class is first loaded.

Dileep
  • 5,362
  • 3
  • 22
  • 38
  • 2
    But the question still remain unanswered. Even if local variables are stored on stack, why are they not assigned default values. – Ankur Shanbhag Aug 14 '13 at 08:21
  • 2
    See Java Language Specification : http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5 Quote: "A local variable (§14.4, §14.14) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified using the rules for definite assignment (§16)." – Robert M. Aug 14 '13 at 08:26
  • @Ankur Look at the last part--- Fields initialization – Dileep Aug 14 '13 at 08:41
1

As local variables are allocated on stack, memory chunk for a local variable is allocated when it is assigned with a value.

Take simple example

class Abc {
   int i = -111;
   int e;

   int doSomething() {
        int a = 10;
        int b = a + i;    
        int c = b + 100;

        Abc d = new Abc();

        e = b + c + d.a;

        return e + 1000;
    }
 }

and the bytecode from javap -c Abc

Compiled from "Abc.java"
class Abc {
  int i;
  int e;

  Abc();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: bipush        -111
       7: putfield      #2                  // Field i:I
      10: return

  int doSomething();
    Code:
       0: bipush        10
       2: istore_1
       3: iload_1
       4: aload_0
       5: getfield      #2                  // Field i:I
       8: iadd
       9: istore_2
      10: iload_2
      11: bipush        100
      13: iadd
      14: istore_3
      15: new           #3                  // class Abc
      18: dup
      19: invokespecial #4                  // Method "<init>":()V
      22: astore        4
      24: aload_0
      25: iload_2
      26: iload_3
      27: iadd
      28: aload         4
      30: getfield      #2                  // Field i:I
      33: iadd
      34: putfield      #5                  // Field e:I
      37: aload_0
      38: getfield      #5                  // Field e:I
      41: sipush        1000
      44: iadd
      45: ireturn
}

When a method is inovked a memory space in the stack called current frame is allocated

If you look carefully even int a=-111; assignment happens in an implicit init function Abc() !

       int a = -111;

       5: bipush        -111
       7: putfield      #2                  // Field a:I

As field variable e is not assigned any value it will be 0 if primitive or null if a Object reference

And if you look at doSomething()

        int a = 10;
        0: bipush        10

for a local to be used the initial value needs to be pushed into stack in this case 10 . without this 'push' [initialization] a's value is not accessible to subsequent statements (as the value is not on the stack). once the value is pushed to stack other operations like iadd istore etc are carried out on the stack

below statement actually creates an object on the heap space and invokes init method. This is where un initialized variables like 'e' gets default values

      15: new           #3                  // class Abc
      18: dup

I leave further bytecode comparison upto you ;) but I hope it is clear

skypjack
  • 49,335
  • 19
  • 95
  • 187
Prashant Bhate
  • 10,907
  • 7
  • 47
  • 82
  • Make up your mind. Either the 'memory chunk' for a local variable is allocated when it is assigned with a value' *or* it is allocated when the method is entered. Not both at the same time. The `ipush` statement pushes the value 10 which the immediately following 'istore' instruction store into the stack slot for `a`. The push does not 'create' `a`. – user207421 Sep 11 '16 at 01:26
0

tl;dr: It was more or less an arbitrary choice

If you ask me, it was a mistake that Java has default values for instance variables. The compiler should have forced the programmer to initialize it before like it is the case for local variables.

The rationale behind the default values is safety. When an object is instantiated, a chunk of memory will be allocated for the object which contains where the instance variables are pointing to etc. The Java designers decided it would be a good idea to wipe this part of memory with zeros and nulls. This way you will never read garbage that happened to be there before the object was allocated. They could have forced initialization; there is nothing fundamental about the choice. It probably made things easy to implement and made enough sense to the designers of Java.

In case of local variables, the designers chose to force initialization (or perhaps it's more accurate to say they chose to not do any kind of initialization when a local variable is only declared, and thus the most logical behavior of the compiler was to force initialization of the variable before use).

Enno Shioji
  • 26,542
  • 13
  • 70
  • 109
  • It would be impossible for the compiler to know when an instance member was used before assignment. The compiler doesn't know which method of the class will be called first. The same analysis on a method on the other hand is certainly possible, as there is only one entry point. – user207421 Sep 11 '16 at 01:28
  • @EJP Kotlin seems to be doing a fairly good job though... – Enno Shioji Sep 11 '16 at 06:31
  • Java does not need to be that smart. – weakish Jul 23 '17 at 08:45