为属性创建构造函数与仅创建属性并使用默认构造函数

cod*_*eme 2 java constructor

当我创建一个关于效率和内存使用的新对象时,我想知道这两个代码片段之间有什么区别。

private Node head;
private int size;

public MyLinkedList(){
    head  = new Node(0,null);
    size = 0;
}
Run Code Online (Sandbox Code Playgroud)

对比

private Node head= new Node(0,null);
private int size = 0;

public MyLinkedList(){

}  
Run Code Online (Sandbox Code Playgroud)

Wil*_*eez 5

当您的对象被编译时,编译器会instance initialization method为您的构造函数创建一个,例如为您的类MyLinkedList,编译器将为您的类的两个版本创建方法,如下所示:

public void <init>(MyLinkedList this) {...}
Run Code Online (Sandbox Code Playgroud)

当您使用new关键字或MyLinkedList.class.newInstance()方法时会调用此方法。

此外,有三种方法可以初始化您的对象:

  • 实例变量初始化(如上面的第二个版本)
  • 实例初始化(如下图)
  • 构造函数(如上面的第一个版本)

实例初始化:

private Node head;
private int size;

{
    Node = new Node(0,null);
    int = 0;
}

public MyLinkedList(){

}
Run Code Online (Sandbox Code Playgroud)

编译器会在方法中放置实例变量初始化代码、实例初始化代码和构造函数体代码<init>。创建新实例时,编译器首先要做的是通过将实例变量初始化为其默认值来为 Object 及其所有实例变量分配内存。此后<init>调用该方法。Java 语言规范中概述了确切的顺序:

这意味着在效率和内存使用方面没有区别,考虑使用哪个取决于您的用例和结构,例如,对于多个构造函数,您可能必须复制初始化代码或确保调用其他构造函数,通过实例初始化,您可以捕获异常或进行更复杂的计算,而这些计算是通过实例变量初始化无法完成的。

为了验证,您可以安装 Eclipse 插件Bytecode Outline并查看生成的字节码指令及其两个版本的类的顺序几乎相同:

MyLinkedList 类两个版本的字节码比较