Java中的类字段初始化序列

Java中的类字段初始化序列,java,initialization,Java,Initialization,以下两段代码的区别是什么: class B{ B(){} } //1) class A{ B b = new B(); } //2) class A{ B b; { b = new B(); } } 这两种方式的初始化有什么不同?另外,如果两个语句都在一个类中,那么它们的执行顺序是什么?为什么 编辑:添加更多说明: class C{ //1) int i = 5; //initializers block { i =7; } } 这

以下两段代码的区别是什么:

class B{
  B(){}
}

//1)
class A{
  B b = new B();
}

//2)
class A{
   B b;
  {
   b = new B();
 }
}
这两种方式的初始化有什么不同?另外,如果两个语句都在一个类中,那么它们的执行顺序是什么?为什么

编辑:添加更多说明:

class C{
//1)  
  int i = 5;

 //initializers block
  {
    i =7;
  }

}
这两条语句的执行顺序是什么?i的最终值是多少?

更新新的更清晰的问题: 现在看来,我应该在我的问题中添加更多的文本。我 想知道两种情况下的执行顺序是什么 这些语句1和2位于同一个类中 变量

您对以下内容感兴趣:

   private class Test {
        public String field = new String("1");
        {
            field = new String("2");
        }

    }
Object obj = new Object() 
首先,字段得到值1,然后调用构造函数,并执行编译时放置在ctor中的init块,因此字段的值为2

请参见此示例:

另请参见此问题和答案:

旧版本 我想你的意思是这样的:

   private class Test {
        public String field = new String("1");
        {
            field = new String("2");
        }

    }
Object obj = new Object() 

花括号定义了给定可变寿命的范围

假设我们有以下示例:

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
    private static void checkObject(Object obj) {
        if (obj == null)
            System.out.println("Object is null");
        else
            System.out.println("Object is not null");
    }
    public static void main (String[] args) throws java.lang.Exception
    {
        Object obj;
        {
            obj = new Object();
            checkObject(obj);
        }
        checkObject(obj);
    }
}
输出为:

Object is not null
Object is not null
但如果我们将其改为:

{
  Object obj = new Object();
  checkObject(obj);
}
checkObject(obj);
它甚至不会编译并给出以下错误消息:

Main.java:22: error: cannot find symbol
        checkObject(obj);
                    ^
  symbol:   variable obj
  location: class Ideone
1 error
第一个声明一个变量obj并在作用域内初始化它 因为它在声明之外,所以可以在作用域之后使用

如果它仅在范围内声明和初始化,则只能在范围内使用。 生存期绑定到范围

如果使用花括号初始化类字段 您可以使用多个语句来初始化它们 但您也可以简单地创建一个最终方法并调用该方法来初始化字段

花括号和字段初始化示例:

class A {
 private String field;
 {
   StringBuilder builder = new StringBuilder("Text").append(value)
                                                    .append(" ")
                                                    .append(otherValue);
   //make some computations 
   //append to builder
   //add to field
   field = builder.toString();
 }
提示:

Java编译器将初始值设定项块复制到每个构造函数中。 因此,这种方法可用于在用户之间共享代码块 多个构造函数

见工作示例:

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
    private static void checkObject(Object obj) {
        if (obj == null)
            System.out.println("Object is null");
        else
            System.out.println("Object is not null");
    }
    public static void main (String[] args) throws java.lang.Exception
    {
        Object obj;
        {
            obj = new Object();
            checkObject(obj);
        }
        checkObject(obj);
    }
}

我认为这与以下几点有关:

初始化实例成员

通常,您会将初始化实例变量的代码放入 构造器。有两种方法可以替代使用构造函数 初始化实例变量:初始化程序块和final方法

实例变量的初始值设定项块看起来就像静态的 初始值设定项阻止,但不包含static关键字:

{
    // whatever code is needed for initialization goes here
}
Java编译器将初始值设定项块复制到每个构造函数中。 因此,这种方法可用于在用户之间共享代码块 多个构造函数

基本上,这意味着括号之间的所有实例变量都将为所有构造函数初始化。即使您的类没有多个构造函数

class A{
  B b;
  int index;
  String result;
  {
    b = new B();
    index = 0;
  }

  public A(int temp){
    // nothing
  }

  public A(int temp, String test){
    this.result = test;
  }

  public int getIndex(){
    return index;
  }
}
添加了具有多个构造函数的示例

class A{
  B b;
  int index;
  String result;
  {
    b = new B();
    index = 0;
  }

  public A(int temp){
    // nothing
  }

  public A(int temp, String test){
    this.result = test;
  }

  public int getIndex(){
    return index;
  }
}

在这里使用哪个构造函数并不重要,因为括号之间的初始化被复制到两个构造函数中。a、 getIndex将始终返回“0”

,因为您知道在实例化类时会调用构造函数。在JAVA中,所有类都有顶级类作为对象。现在,无论何时我们为您的案例调用任何类的构造函数,它都会导致我们调用第一个超级引导对象的构造函数

现在在示例1中,变量b在类本身中声明并初始化。因此,在类A的构造函数被执行之前,变量b被初始化,也就是说,在公共A中编写的所有代码都将在b被初始化之后执行

在示例2中,变量b在类中声明,但在A的构造函数中初始化。如果在行b=新b之前有一些代码;首先执行该代码,然后初始化b

请参见下面的示例:

Class A{
   B b = new B();

   public A(){
      b == null; //FALSE as it has been already initialised.
   }
}
但是


您可以发布可编译的代码吗?是的,您的代码甚至不会像现在这样编译。您编写的代码不是有效的java代码。请编辑相同的内容并再次发布。对于案例2,您没有为任何内容分配b,而是为实例初始值设定项创建了一个单独的局部变量b。如果你的意思是b=新的b;那么第一个和第二个示例是等效的。在这两个示例中,成员变量的初始化是在隐式创建的无参数构造函数A中对super的隐式调用之后执行的。@W vd L,我知道初始化器块。我想知道的是,如果1我们在任何块之外创建obejectin类声明,2我们在初始值设定项块中创建一个对象,会有什么不同。。init块用于在使用多个重载构造函数时简化代码。让我再举一个例子