为什么实例变量在java中有默认值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18226405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do instance variables have default values in java?
提问by Shikhil Bhalla
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?
为什么在类中声明的变量有默认值,而在方法中声明的变量,称为“局部变量”,在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.
在上面的示例中,变量的a
默认值为 0,但变量b
给出了它可能尚未初始化的错误。
采纳答案by Ashwani
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.
所有成员变量都必须加载到堆中,因此在创建类的实例时必须使用默认值进行初始化。在局部变量的情况下,它们不会被加载到堆中,它们存储在堆栈中,直到它们在 java 7 之前被使用,因此我们需要显式初始化它们。现在“Java Hotspot Server Compiler”执行“逃逸分析”并决定在堆栈而不是堆上分配一些变量。
回答by Dileep
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:
编译器抱怨在 (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)
}
}
Fields initialization
字段初始化
If no initialization is providedfor 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.
如果在声明时或在初始化程序块中没有为实例或静态变量提供初始化,则使用其 type 的默认值隐式初始化。一个实例变量被初始化,其类型的每个类被实例化时间的缺省值,也就是对于从类创建的每个对象。静态变量在类首次加载时使用其类型的默认值进行初始化。
回答by Enno Shioji
tl;dr: It was more or less an arbitrary choice
tl;dr:这或多或少是一个任意的选择
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.
如果你问我,Java 有实例变量的默认值是错误的。编译器应该强制程序员在初始化它之前像局部变量的情况一样。
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.
默认值背后的基本原理是安全。当一个对象被实例化时,将为该对象分配一块内存,其中包含实例变量所指向的位置等。Java 设计者决定用零和空值擦除这部分内存是个好主意。这样,您将永远不会读取在分配对象之前碰巧存在的垃圾。他们可以强制初始化;选择没有什么基本的。它可能使事情更容易实现并且对 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).
在局部变量的情况下,设计者选择强制初始化(或者更准确地说,当只声明局部变量时,他们选择不进行任何类型的初始化,因此编译器最合乎逻辑的行为是强制初始化使用前的变量)。
回答by Prashant Bhate
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
和字节码来自 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 frameis allocated
当一个方法被调用时,堆栈中称为当前帧的内存空间被分配
If you look carefully even int a=-111;
assignment happens in an implicit init function Abc()
!
如果您仔细观察,即使int a=-111;
赋值也会发生在隐式 init 函数中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
由于字段变量e
未分配任何值,如果是原始值,则为 0,如果是对象引用,则为 null
And if you look at doSomething()
如果你看 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
对于要使用的本地,在这种情况下需要将初始值推入堆栈 10 。没有这个“推”[初始化] a 的值不能被后续语句访问(因为该值不在堆栈上)。一旦将值推送到堆栈,其他操作(如 iadd istore 等)将在堆栈上执行
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
下面的语句实际上在堆空间上创建一个对象并调用 init 方法。这是像“e”这样的未初始化变量获得默认值的地方
15: new #3 // class Abc
18: dup
I leave further bytecode comparison upto you ;) but I hope it is clear
我将进一步的字节码比较留给您;) 但我希望它很清楚