java构造函数顺序
这个java程序很简单,而且有很多注释,因此您可以很快理解它。但是,为什么在construct staff[1]中,程序首先转到以下语句:java构造函数顺序,java,constructor,Java,Constructor,这个java程序很简单,而且有很多注释,因此您可以很快理解它。但是,为什么在construct staff[1]中,程序首先转到以下语句: this("Employee #" + nextId, s); 然后转到对象初始化块,然后返回语句,如何混淆。为什么不先使用对象初始化块 import java.util.*; public class ConstructorTest { public static void main(String[] args) { // fi
this("Employee #" + nextId, s);
然后转到对象初始化块,然后返回语句,如何混淆。为什么不先使用对象初始化块
import java.util.*;
public class ConstructorTest
{
public static void main(String[] args)
{
// fill the staff array with three Employee objects
Employee[] staff = new Employee[3];
staff[0] = new Employee("Harry", 40000);
staff[1] = new Employee(60000);
staff[2] = new Employee();
// print out information about all Employee objects
for (Employee e : staff)
System.out.println("name=" + e.getName()
+ ",id=" + e.getId()
+ ",salary=" + e.getSalary());
}
}
class Employee
{
// three overloaded constructors
public Employee(String n, double s)
{
name = n;
salary = s;
}
public Employee(double s)
{
// calls the Employee(String, double) constructor
this("Employee #" + nextId, s);
}
// the default constructor
public Employee()
{
// name initialized to ""--see below
// salary not explicitly set--initialized to 0
// id initialized in initialization block
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public int getId()
{
return id;
}
private static int nextId;
private int id;
private String name = ""; // instance field initialization
private double salary;
// static initialization block
static
{
Random generator = new Random();
// set nextId to a random number between 0 and 9999
nextId = generator.nextInt(10000);
}
// object initialization block
{
id = nextId;
nextId++;
}
}
因为这个(“雇员”#“+nextId,s)
包含对超类构造函数的隐式调用,当然必须在子类的初始值设定项块之前执行
使用实例初始值设定项通常是一个坏主意,因为它们并不广为人知,只能做构造函数,两者混合会导致混乱。因为这(“Employee#”+nextId,s)
包含对超类构造函数的隐式调用,当然必须在子类的初始值设定项块之前执行
使用实例初始值设定项通常是一个坏主意,因为它们并不广为人知,只能使用构造函数,两者混合会导致混淆。这遵循第节中指定的顺序: (最后两颗子弹) 让C成为被实例化的类,让我们成为C的直接超类,让我成为被创建的实例。显式构造函数调用的评估过程如下:
- 首先,如果构造函数调用语句是超类构造函数调用, (被剪掉了,因为这不是我们的情况)
- 接下来,调用构造函数
- 最后,如果构造函数调用语句是超类构造函数调用,并且构造函数调用语句正常完成,则执行C的所有实例变量初始值设定项和C的所有实例初始值设定项。(Snip)备用构造函数调用不会执行此额外的隐式操作
因此,在调用超级构造函数之后立即执行实例初始值设定项,这(隐式地)来自
public Employee(String n,double s)
。这应该在执行该双参数构造函数的主体之前发生。这遵循第节中指定的顺序:
(最后两颗子弹)
让C成为被实例化的类,让我们成为C的直接超类,让我成为被创建的实例。显式构造函数调用的评估过程如下:
- 首先,如果构造函数调用语句是超类构造函数调用, (被剪掉了,因为这不是我们的情况)
- 接下来,调用构造函数
- 最后,如果构造函数调用语句是超类构造函数调用,并且构造函数调用语句正常完成,则执行C的所有实例变量初始值设定项和C的所有实例初始值设定项。(Snip)备用构造函数调用不会执行此额外的隐式操作
因此,在调用超级构造函数之后立即执行实例初始值设定项,这(隐式地)来自
public Employee(String n,double s)
。这应该在执行双参数构造函数的主体之前发生。不确定实际问题是什么,这有点令人困惑。初始化顺序(静态、对象、构造函数)是预定义的,与它们在代码中出现的顺序无关。至于常规样式,我通常不鼓励使用对象初始化块。这是一个非常常见的错误源,它使异常处理更加复杂,并且很难调试。此外,它不是一种非常常见的模式,因此开发人员在分析bug时往往会错过寻找它的机会。不确定实际问题是什么,这有点令人困惑。初始化顺序(静态、对象、构造函数)是预定义的,与它们在代码中出现的顺序无关。至于常规样式,我通常不鼓励使用对象初始化块。这是一个非常常见的错误源,它使异常处理更加复杂,并且很难调试。此外,它不是一种非常常见的模式,因此开发人员在分析bug时往往会错过寻找它的机会。Java编译器必须确保从每个构造函数调用对象初始化块中的代码。对于大多数构造函数,它是通过在对super()
的隐式或显式调用之后将代码插入构造函数来实现的。但是,对于以this()
开头的编译器,首先没有对super()
的隐式调用——另一个构造函数处理这个问题。其次,在这样的构造函数中,根本不能插入对象初始值设定项块,因为在调用第二个构造函数时会提取代码。因此,this()
调用是发生的第一件事。Java编译器必须确保从每个构造函数调用对象初始化块中的代码。对于大多数构造函数,它是通过在对super()
的隐式或显式调用之后将代码插入构造函数来实现的。但是,对于以this()
开头的编译器,首先没有对super()
的隐式调用——另一个构造函数处理这个问题。其次,在这样的构造函数中,根本不能插入对象初始值设定项块,因为在调用第二个构造函数时会提取代码。因此,this()
调用是发生的第一件事。听起来像是在问为什么在实例初始值设定项块之前执行this
语句。这是正确的吗?听起来像是在问为什么在实例初始值设定项块之前执行此
语句。对吗?