为什么在java中实例变量有默认值?

为什么在java中实例变量有默认值?,java,class,Java,Class,为什么类中声明的变量有默认值,而方法中声明的变量(称为“局部变量”)在Java中没有默认值 比如说 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); } } 在上面的示例中,变

为什么类中声明的变量有默认值,而方法中声明的变量(称为“局部变量”)在Java中没有默认值

比如说

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);
    }
 }

在上面的示例中,变量
a
的默认值为0,但变量
b
给出的错误是它可能尚未初始化。

局部变量初始化

在方法和块中声明的变量称为局部变量。局部变量在方法调用时创建时未初始化。因此,局部变量在使用之前必须显式初始化。否则,编译器将在执行包含方法或块时将其标记为错误

示例:

public class SomeClassName{

public static void main(String args[]){
int total;
System.out.println("The incremented total is " + total + 3); //(1)
}
}
编译器抱怨(1)处println语句中使用的局部变量total可能未初始化。 在使用前初始化局部变量total可解决此问题:

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)
}
}
字段初始化

如果实例或静态变量在声明时或在初始化程序块中未提供初始化,则它将使用其类型的默认值进行隐式初始化。 每次实例化类时,实例变量都会使用其类型的默认值初始化,即针对从该类创建的每个对象。
静态变量在第一次加载类时使用其类型的默认值初始化。

所有成员变量都必须加载到堆中,以便在创建类实例时使用默认值初始化它们。对于局部变量,在Java7之前使用它们之前,它们不会加载到堆中,而是存储在堆栈中,所以我们需要显式地初始化它们。
现在,“Java热点服务器编译器”执行“转义分析”,并决定在堆栈上而不是堆上分配一些变量;博士:这或多或少是一个武断的选择

如果你问我,Java对实例变量有默认值是一个错误。编译器应该在编译之前强制程序员初始化它,就像局部变量的情况一样

默认值背后的基本原理是安全。当一个对象被实例化时,将为该对象分配一块内存,该对象包含实例变量所指向的位置等。Java设计人员决定用零和空擦除这部分内存是一个好主意。这样,您将永远不会读取在分配对象之前碰巧存在的垃圾。它们可以强制初始化;这个选择没有什么根本性的。它可能使事情易于实现,并且对Java的设计者来说有足够的意义


对于局部变量,设计人员选择强制初始化(或者更准确地说,当仅声明局部变量时,他们选择不进行任何类型的初始化,因此编译器最合乎逻辑的行为是在使用前强制初始化变量).

当局部变量在堆栈上分配时,局部变量的内存块在赋值时分配

举个简单的例子

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;
    }
 }
以及
javap-cbc

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
}
由于未为字段变量
e
分配任何值,因此,如果原语为0,如果对象引用为null,则为0

如果你看
doSomething()

对于要使用的局部变量,需要将初始值推入堆栈(在本例中为10)。如果没有此“推送”[初始化],后续语句将无法访问a的值(因为该值不在堆栈上)。一旦将该值推送到堆栈,其他操作(如iadd istore等)将在堆栈上执行

下面的语句实际上在堆空间上创建一个对象并调用init方法。这是未初始化变量(如“e”)获取默认值的地方

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

我将进一步的字节码比较留给您;)但是我希望很清楚,

inta
实际上有一个默认值
0
。对象的整个内存块总是用零填充,这就是为什么对象中的所有变量都默认为0,
b
是一个局部变量,只是没有在该部分初始化。赋值时会初始化它,但y b变量没有默认值?
b
是在堆栈中分配的,与
a
不同,出于性能原因,它不会被置零。(或者更准确地说:不需要实现来清除它,因为它必然会限制实现的性能,从而获得很少的收益)请使用大写字母——我再也不会编辑您的文章了,但这个问题仍然没有答案。即使局部变量存储在堆栈上,为什么不给它们分配默认值呢?请参阅Java语言规范:Quote:“局部变量(§14.4,§14.14)在使用之前,必须通过初始化(§14.4)或赋值(§15.26)显式给定一个值,并且可以使用明确赋值的规则进行验证(§16)."@Ankur看最后一部分--Fields initializationLocal variables loaded to heap?你注意到OP谈论的是一个int,这是一个基元类型吗?o.OHe只是以
int
为例。但是,如果你有一个local variable
对象o
,引用仍然存在于堆栈中,而不是在堆中。如果你不初始化ize
o
,使用它是一个错误——问题是在没有初始化的情况下使用引用。如果您只需执行
o=null
,则可以使用它:您已经初始化了引用,引用仍然存在于堆栈中(不在堆中),并且没有任何内容“加载到堆中”在此初始化之后。如果执行
o=new Object()
,则您已经触及了堆,但这与无法
        int a = 10;
        0: bipush        10
      15: new           #3                  // class Abc
      18: dup