class 字段 Java 中的初始化顺序
class fields Initialization sequence in Java
下面两段代码有什么区别:
class B{
B(){}
}
//1)
class A{
B b = new B();
}
//2)
class A{
B b;
{
b = new B();
}
}
这两种方式初始化有什么区别?另外,如果两个语句都在一个 class 中,它们的执行顺序是什么?为什么?
编辑:添加更多说明:
class C{
//1)
int i = 5;
//initializers block
{
i =7;
}
}
这两个语句的执行顺序是什么? i 的最终值是多少?
更新更清晰的新问题:
It sees now that I should have added more text to my question. I
wanted to know what would be the sequence of execution in case both
these statements(1 and 2) are in one single class for the same
variable ?
您对以下内容感兴趣:
private class Test {
public String field = new String("1");
{
field = new String("2");
}
}
一开始field的值为1,之后会调用constructor,执行编译时放在ctor中的init block,所以field的值为"2"。
看这个例子:
另请参阅此问答:
Default constructor vs. inline field initialization
旧版本
我想你的意思是这样的:
Object obj = new Object()
或者
Object obj;
{
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字段
您可以使用多个语句来初始化它们
但您也可以简单地创建一个 final 方法并调用该方法来初始化该字段。
大括号和字段初始化示例:
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();
}
提示:
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
查看工作示例:
我认为它与以下内容有关:
Initializing Instance Members
Normally, you would put code to initialize an instance variable in a
constructor. There are two alternatives to using a constructor to
initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
基本上这意味着所有构造函数都将初始化括号之间的所有实例变量。即使您的 类 没有多个构造函数
添加了具有多个构造函数的示例
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() 将始终 return '0'
如您所知,当我们实例化一个 class 时会调用构造函数。此外,所有 classes 都具有顶级 Class,如 JAVA 中的 Object
。现在,每当我们为您的案例 A
调用任何 class 的构造函数作为 new A()
时,它都会导致我们首先调用 super()
导致 Object's
构造函数。
现在,在您的示例 1 中,您的变量 b
已在 class 本身中声明和初始化。因此,在 class A
的构造函数执行之前,变量 b
被初始化,即您在 public A()
中编写的所有代码将在 b
之后执行初始化。
在您的示例 2 中,您的变量 b
在 class 中声明,但在 A
的构造函数中初始化。如果您在 b = new B();
行之前有一些代码,那么该代码将首先执行,然后 b
将被初始化。
参见下面的示例:
Class A{
B b = new B();
public A(){
b == null; //FALSE as it has been already initialised.
}
}
但是
Class A{
B b ;
public A(){
b == null; //TRUE as it has not been initialised.
b = new B();
b == null; //FALSE as it has been just initialised.
}
}
下面两段代码有什么区别:
class B{
B(){}
}
//1)
class A{
B b = new B();
}
//2)
class A{
B b;
{
b = new B();
}
}
这两种方式初始化有什么区别?另外,如果两个语句都在一个 class 中,它们的执行顺序是什么?为什么?
编辑:添加更多说明:
class C{
//1)
int i = 5;
//initializers block
{
i =7;
}
}
这两个语句的执行顺序是什么? i 的最终值是多少?
更新更清晰的新问题:
It sees now that I should have added more text to my question. I wanted to know what would be the sequence of execution in case both these statements(1 and 2) are in one single class for the same variable ?
您对以下内容感兴趣:
private class Test {
public String field = new String("1");
{
field = new String("2");
}
}
一开始field的值为1,之后会调用constructor,执行编译时放在ctor中的init block,所以field的值为"2"。
看这个例子:
另请参阅此问答:
Default constructor vs. inline field initialization
旧版本
我想你的意思是这样的:
Object obj = new Object()
或者
Object obj;
{
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字段 您可以使用多个语句来初始化它们 但您也可以简单地创建一个 final 方法并调用该方法来初始化该字段。
大括号和字段初始化示例:
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();
}
提示:
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
查看工作示例:
我认为它与以下内容有关:
Initializing Instance Members
Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
{ // whatever code is needed for initialization goes here }
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
基本上这意味着所有构造函数都将初始化括号之间的所有实例变量。即使您的 类 没有多个构造函数
添加了具有多个构造函数的示例
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() 将始终 return '0'
如您所知,当我们实例化一个 class 时会调用构造函数。此外,所有 classes 都具有顶级 Class,如 JAVA 中的 Object
。现在,每当我们为您的案例 A
调用任何 class 的构造函数作为 new A()
时,它都会导致我们首先调用 super()
导致 Object's
构造函数。
现在,在您的示例 1 中,您的变量 b
已在 class 本身中声明和初始化。因此,在 class A
的构造函数执行之前,变量 b
被初始化,即您在 public A()
中编写的所有代码将在 b
之后执行初始化。
在您的示例 2 中,您的变量 b
在 class 中声明,但在 A
的构造函数中初始化。如果您在 b = new B();
行之前有一些代码,那么该代码将首先执行,然后 b
将被初始化。
参见下面的示例:
Class A{
B b = new B();
public A(){
b == null; //FALSE as it has been already initialised.
}
}
但是
Class A{
B b ;
public A(){
b == null; //TRUE as it has not been initialised.
b = new B();
b == null; //FALSE as it has been just initialised.
}
}