java构造函数顺序
这个java程序很简单,注释也很多,所以你很快就能理解它。但是,为什么在构造staff[1]时,程序首先转到语句:
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++;
}
}
This java program is easy and full of comment,so you can understand it fast.however,why in construct staff[1],the program first go to the statement:
this("Employee #" + nextId, s);
then go to the object initialization block,and then go back to the statement,how confusion.why not it first use the object initialization block
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++;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为
this("Employee #" + nextId, s);
包含对超类构造函数的隐式调用,当然必须在子类的初始化块之前执行。使用实例初始化器通常是一个坏主意,因为它们并不为人所知,除了构造函数之外不能做任何事情,并且混合两者会导致混乱。
Because
this("Employee #" + nextId, s);
includes an implicit call to the superclass constructor, which of course must be executed before the initializer block of the subclass.Using instance initializers is generally a bad idea as they are not well known, cannot do anything more than constructors, and mixing both leads to confusion.
这遵循 JLS 的 8.8.7.1 节中指定的顺序:(
最后两颗子弹)
因此,实例初始值设定项在调用超级构造函数后立即执行 - 这是(隐式)来自
public Employee(String n, double s)
。这应该在执行该两参数构造函数的主体之前发生。This follows the order specified in section 8.8.7.1 of the JLS:
(Final two bullets)
So the instance initializer is executed immediately after the superconstructor is called - which is (implicitly) from
public Employee(String n, double s)
. This should happen before the body of that two-parameter constructor is executed.不确定实际问题是什么,有点令人困惑。初始化(静态、对象、构造函数)的顺序是预定义的,与它们在代码中出现的顺序无关。至于一般风格,我通常不鼓励使用对象初始化块。这是一个非常常见的错误源,它使异常处理更加复杂并且难以调试。此外,这不是一种非常常见的模式,因此开发人员在分析错误时往往会错过寻找它。
Not sure what the actual question is, it's a bit confusing. The order of initialization (static, object, constructor) is predefined and has nothing to do with in which order they appear in the code. As for the general style, I generally discourage using object initialization blocks. It's a very common source of errors, it makes exception-handling more complex and it's hard to debug. In addition, it's not a very common pattern so developers tend to miss looking for it when analyzing bugs.
Java 编译器必须确保从每个构造函数中调用对象初始化块中的代码。对于大多数构造函数,它通过在隐式或显式调用
super()
之后将代码插入到构造函数中来实现此目的。然而,对于以this()
开头的编译器,首先,没有对super()
的隐式调用——其他构造函数处理那。其次,在这样的构造函数中,根本无法插入对象初始值设定项块,因为在调用第二个构造函数时将拾取代码。因此,this()
调用是首先发生的事情。The Java compiler must ensure that the code in the object initialization block is called from each constructor. For most constructors, it does this by inserting the code into the constructor right after the implicit or explicit call to
super()
. For compilers that start withthis()
, however, first of all there is no implicit call tosuper()
-- the other constructor handles that. Secondly, in such a constructor the object initializer block can't be inserted at all, since the code will be picked up when the second constructor is called. Therefore thethis()
call is the very first thing that happens.