📜  Java中的构造函数链接与示例

📅  最后修改于: 2022-05-13 01:54:59.863000             🧑  作者: Mango

Java中的构造函数链接与示例

先决条件Java中的构造函数
构造函数链接是相对于当前对象从另一个构造函数调用一个构造函数的过程。
构造函数链接可以通过两种方式完成:

  • 在同一类中:可以对同一类中的构造函数使用this()关键字来完成
  • 从基类:通过使用super()关键字从基类调用构造函数。

构造函数链接通过继承发生。子类构造函数的任务是首先调用超类的构造函数。这确保了子类对象的创建从超类的数据成员的初始化开始。继承链中可以有任意数量的类。每个构造函数都会调用链,直到到达顶部的类。
为什么我们需要构造函数链?
当我们想要在单个构造函数中执行多个任务时使用此过程,而不是在单个构造函数中为每个任务创建代码,我们为每个任务创建一个单独的构造函数并使其链,从而使程序更具可读性。

使用 this() 关键字在同一类中进行构造函数链接:

Java中的构造函数链

Java
// Java program to illustrate Constructor Chaining
// within same class Using this() keyword
class Temp
{
    // default constructor 1
    // default constructor will call another constructor
    // using this keyword from same class
    Temp()
    {
        // calls constructor 2
        this(5);
        System.out.println("The Default constructor");
    }
 
    // parameterized constructor 2
    Temp(int x)
    {
        // calls constructor 3
        this(5, 15);
        System.out.println(x);
    }
 
    // parameterized constructor 3
    Temp(int x, int y)
    {
        System.out.println(x * y);
    }
 
    public static void main(String args[])
    {
        // invokes default constructor first
        new Temp();
    }
}


Java
// Java program to illustrate Constructor Chaining
// within same class Using this() keyword
// and changing order of constructors
class Temp
{
    // default constructor 1
    Temp()
    {
        System.out.println("default");
    }
 
    // parameterized constructor 2
    Temp(int x)
    {
        // invokes default constructor
        this();
        System.out.println(x);
    }
 
    // parameterized constructor 3
    Temp(int x, int y)
    {
        // invokes parameterized constructor 2
        this(5);
        System.out.println(x * y);
    }
 
    public static void main(String args[])
    {
        // invokes parameterized constructor 3
        new Temp(8, 10);
    }
}


Java
// Java program to illustrate Constructor Chaining to
// other class using super() keyword
class Base
{
    String name;
 
    // constructor 1
    Base()
    {
        this("");
        System.out.println("No-argument constructor of" +
                                           " base class");
    }
 
    // constructor 2
    Base(String name)
    {
        this.name = name;
        System.out.println("Calling parameterized constructor"
                                              + " of base");
    }
}
 
class Derived extends Base
{
    // constructor 3
    Derived()
    {
        System.out.println("No-argument constructor " +
                           "of derived");
    }
 
    // parameterized constructor 4
    Derived(String name)
    {
        // invokes base class constructor 2
        super(name);
        System.out.println("Calling parameterized " +
                           "constructor of derived");
    }
 
    public static void main(String args[])
    {
        // calls parameterized constructor 4
        Derived obj = new Derived("test");
 
        // Calls No-argument constructor
        // Derived obj = new Derived();
    }
}


Java
class Temp
{
    // block to be executed before any constructor.
    {
        System.out.println("init block");
    }
 
    // no-arg constructor
    Temp()
    {
        System.out.println("default");
    }
 
    // constructor with one argument.
    Temp(int x)
    {
        System.out.println(x);
    }
 
    public static void main(String[] args)
    {
        // Object creation by calling no-argument
        // constructor.
        new Temp();
 
        // Object creation by calling parameterized
        // constructor with one parameter.
        new Temp(10);
    }
}


Java
class Temp
{
    // block to be executed first
    {
        System.out.println("init");
    }
    Temp()
    {
        System.out.println("default");
    }
    Temp(int x)
    {
        System.out.println(x);
    }
 
    // block to be executed after the first block
    // which has been defined above.
    {
        System.out.println("second");
    }
    public static void main(String args[])
    {
        new Temp();
        new Temp(10);
    }
}


输出:

75
5
The Default constructor

构造函数链接规则:

  1. this()表达式应该始终是构造函数的第一行。
  2. 至少应该有一个没有 this() 关键字的构造函数(上面示例中的构造函数 3)。
  3. 可以按任何顺序实现构造函数链接。

如果我们改变构造函数的顺序会发生什么?
没什么,构造函数链可以按任意顺序实现

Java

// Java program to illustrate Constructor Chaining
// within same class Using this() keyword
// and changing order of constructors
class Temp
{
    // default constructor 1
    Temp()
    {
        System.out.println("default");
    }
 
    // parameterized constructor 2
    Temp(int x)
    {
        // invokes default constructor
        this();
        System.out.println(x);
    }
 
    // parameterized constructor 3
    Temp(int x, int y)
    {
        // invokes parameterized constructor 2
        this(5);
        System.out.println(x * y);
    }
 
    public static void main(String args[])
    {
        // invokes parameterized constructor 3
        new Temp(8, 10);
    }
}

输出:

default
5
80

注意:在示例 1 中,最后调用默认构造函数,但在示例 2 中,首先调用默认构造函数。因此,构造函数链接中的顺序并不重要。

使用 super() 关键字的构造函数链接到其他类:

Java

// Java program to illustrate Constructor Chaining to
// other class using super() keyword
class Base
{
    String name;
 
    // constructor 1
    Base()
    {
        this("");
        System.out.println("No-argument constructor of" +
                                           " base class");
    }
 
    // constructor 2
    Base(String name)
    {
        this.name = name;
        System.out.println("Calling parameterized constructor"
                                              + " of base");
    }
}
 
class Derived extends Base
{
    // constructor 3
    Derived()
    {
        System.out.println("No-argument constructor " +
                           "of derived");
    }
 
    // parameterized constructor 4
    Derived(String name)
    {
        // invokes base class constructor 2
        super(name);
        System.out.println("Calling parameterized " +
                           "constructor of derived");
    }
 
    public static void main(String args[])
    {
        // calls parameterized constructor 4
        Derived obj = new Derived("test");
 
        // Calls No-argument constructor
        // Derived obj = new Derived();
    }
}

输出:

Calling parameterized constructor of base
Calling parameterized constructor of derived

注意:类似于同一个类中的构造函数链接, super()应该是构造函数的第一行,因为超类的构造函数在子类的构造函数之前被调用。
替代方法:使用初始化块
当我们希望每个构造函数都执行某些公共资源时,我们可以将代码放在init 块中。每当构造函数用于创建新对象时,初始化块总是在任何构造函数之前执行。
示例 1:

Java

class Temp
{
    // block to be executed before any constructor.
    {
        System.out.println("init block");
    }
 
    // no-arg constructor
    Temp()
    {
        System.out.println("default");
    }
 
    // constructor with one argument.
    Temp(int x)
    {
        System.out.println(x);
    }
 
    public static void main(String[] args)
    {
        // Object creation by calling no-argument
        // constructor.
        new Temp();
 
        // Object creation by calling parameterized
        // constructor with one parameter.
        new Temp(10);
    }
}

输出:

init block
default
init block
10

注意:如果有多个块,它们将按照它们在同一类中定义的顺序执行。见前。
例子 :

Java

class Temp
{
    // block to be executed first
    {
        System.out.println("init");
    }
    Temp()
    {
        System.out.println("default");
    }
    Temp(int x)
    {
        System.out.println(x);
    }
 
    // block to be executed after the first block
    // which has been defined above.
    {
        System.out.println("second");
    }
    public static void main(String args[])
    {
        new Temp();
        new Temp(10);
    }
}

输出 :

init
second
default
init
second
10