简体   繁体   English

Java实例变量内部和外部构造函数的初始化混乱

[英]Java instance variable initialization inside and outside constructor confusion

Lets see a small snippet of java code 让我们看一小段Java代码

class Foo {
  int i = 0;
  int j;
  public Foo(int j){
     this.j = j;
  }
}

Above example shows two ways of initializing variables in Java. 上面的示例显示了Java中初始化变量的两种方法。 But my question is which variable first get initialized? 但是我的问题是哪个变量首先被初始化? The variable outside the constructor or the variable inside the constructor? 构造函数外部的变量还是构造函数内部的变量? When I instantiate the above class Foo foo = new Foo(5) , I know that the constructor of the class get called which implies variable j get initialized first. 当我实例化上面的类Foo foo = new Foo(5) ,我知道该类的构造函数被调用,这意味着变量j首先被初始化。 Can anyone make me clear about the ordering. 谁能让我清楚订购的信息。

Precedence 优先顺序

In your case the int j happens first and defaults to 0 , then gets reassigned to 5 when the constructor is called on to create a new instance. 在您的情况下, int j首先发生并且默认为0 ,然后在构造函数被调用以创建新实例时重新分配为5

j only gets re-assigned when the constructor runs. j仅在构造函数运行时重新分配。 Instance members get initialized first when you assign them something outside the constructor. 当您在构造函数之外分配实例成员时,实例成员首先被初始化。

Order of Execution 执行命令

Each line of code gets executed in the order it appears. 每行代码都按其显示顺序执行。 The declarations happen before the constructor always, in the order they are listed in the code. 声明总是按照代码中列出的顺序在构造函数之前发生。

Deterministic and Predictable 确定性和可预测性

You should only initialize instance members in a single place, inside a single constructor. 您只应在单个构造函数中的单个位置初始化实例成员。

Relying on defaults leads to hard to track down bugs, and makes testing a nightmare, but a instance member that is unassigned will stand out like a sore thumb to the IDE, the compiler and at runtime. 依赖默认值会导致难以跟踪错误,并使测试成为噩梦,但是未分配的实例成员会像对IDE,编译器和运行时的烦恼一样脱颖而出。 Unfortunately for primitives like int they default to 0 which might not be what you want/need. 不幸的是,对于像int这样的基元,它们默认为0 ,这可能不是您想要/不需要的。

A better design is: 更好的设计是:

 private final int j;

 public Foo(final int j) { this.j = j; }

This keeps the j from getting assigned anything on initialization and you never have to worry about it changing. 这样可以避免在初始化时为j分配任何东西,而您不必担心它会发生变化。

Let's say you have this class 假设您有这堂课

public class Test
{
    int i = 4;

    public Test()
    {
        System.out.println(i);
    }  
}

When you create an instance of Test , the output will be 4 . 创建Test的实例时,输出为4 This means that the initialization goes first. 这意味着初始化首先进行。 Then the constructor is called. 然后调用构造函数。 Because if the constructor were first and the initialization of i second, you won't get 4 as output. 因为如果构造函数是第一个,而i的初始化是第二个,则不会得到4作为输出。

int i = 0;

i is an instance variable and hence will get default value which is 0. So you don't need to assign 0 to it explicitly. 我是一个实例变量,因此将获得默认值0。因此,您无需显式分配0。

Coming to your question 来问你的问题

 But my question is which variable first get initialized?

Then the answer would be i is initialized before j. 然后答案是i在j之前初始化。 Because if you see byte codes of your snippet Object is created first which will initialize your instance variables and then constructor is called. 因为如果您看到代码段的字节码,则首先创建对象,这将初始化您的实例变量,然后调用构造函数。

When ever you create Object creation, First declaration of variable are being done.After that only variables are defined. 无论何时创建对象创建,都会先进行变量的声明,然后才定义变量。 In your case first "j" variable will declared first ie class variable.After that the value will be assigned to "j" in constructor of a class. 在您的情况下,将首先声明“ j”变量,即类变量。此后,该值将在类的构造函数中分配给“ j”。

Ordering :- 订购:-

  1. First of all static initilization blocks are executed.(If any) 首先执行静态初始化块。(如果有)
  2. Then execution starts from main method. 然后从main方法开始执行。

for your question I think i and j will be initailized together as i=0 ; 对于您的问题,我认为当i=0ij将会一起出现。 and j as 0 (with int default value.) j为0(具有int默认值。)

Because in constructor you are just changing the value. 因为在构造函数中,您只是在更改值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM