1. Copy Constructor trong Java

Trong Java không có Copy Constructor như trong C++. Tuy nhiên, ta có thể sao chép các giá trị của một đối tượng tới đối tượng khác giống như sử dụng một hàm copy constructor trong C ++. Khác với việc sử dụng hàm constructor để sao chép giá trị từ đối tượng này sang đối tượng khác, điều tương tự cũng có thể được thực hiện bằng cách:

  • Gán các giá trị của một đối tượng cho đối tượng khác
  • Sử dụng phương thức clone() của Object class

Ví dụ: sao chép các giá trị của một đối tượng vào trong đối tượng khác sử dụng Constructor

class Main{  
    int id;  
    String name; 
    // Constructor 2 tham số 
    Main(int i,String n){  
      id = i;  
      name = n;  
    }  
    // Constructor
    Main(Main s){  
      id = s.id;  
      name =s.name;  
    }  
    // Phương thức
    void display(){
      System.out.println(id+" "+name);
    }  

    public static void main(String args[]){  
      // Tạo đối tượng
      Main s1 = new Main(19,"Lập trình từ đầu");  
      Main s2 = new Main(s1);  
      // Gọi phương thức
      s1.display();  
      s2.display();  
   }  
}

Kết quả

19 Lập trình từ đầu
19 Lập trình từ đầu

2. Coppy giá trị mà không sử dụng Constructor

Chúng ta có thể sao chép các giá trị của một đối tượng vào trong đối tượng khác bởi gán các giá trị của đối tượng đó vào trong đối tượng khác. Trong trường hợp này, chúng ta không cần tạo Constructor.

Ví dụ:

class Main{  
    int id;  
    String name;  
    Main(int i,String n){  
      id = i;  
      name = n;  
    }  
    Main(){}  
    void display(){System.out.println(id+" "+name);}  

    public static void main(String args[]){  
      Main s1 = new Main(19,"Lập trình từ đầu");  
      Main s2 = new Main();  
      s2.id=s1.id;  
      s2.name=s1.name;  
      s1.display();  
      s2.display();  
   }  
}

Kết quả

19 Lập trình từ đầu
19 Lập trình từ đầu

3. Constructor Chaining trong Java

Constructor Chaining là việc xây dựng chuỗi ở đây là quá trình gọi một hàm tạo này từ một hàm tạo khác đối với đối tượng hiện tại. Nó có thể được thực hiện theo 2 cách:

  • Trong cùng một lớp : Nó có thể được thực hiện bằng cách sử dụng từ khóa this() cho các hàm tạo trong cùng một lớp
  • Từ lớp cơ sở: bằng cách sử dụng từ khóa super() để gọi hàm tạo từ lớp cơ sở.

Chuỗi xây dựng xảy ra thông qua kế thừa . Nhiệm vụ của hàm tạo lớp con là gọi hàm tạo của lớp siêu đầu tiên. Điều này đảm bảo rằng việc tạo đối tượng của lớp con bắt đầu bằng việc khởi tạo các thành viên dữ liệu của lớp siêu. Có thể có bất kỳ số lượng lớp nào trong chuỗi kế thừa. Mọi hàm tạo gọi lên chuỗi cho đến khi đạt đến lớp ở trên cùng.

Ví dụ:

// Chương trình Java để minh họa Constructor Chaining
// trong cùng một lớp Sử dụng từ khóa this ()
class Main
{
    // hàm tạo mặc định 1
    // hàm tạo mặc định sẽ gọi một hàm tạo khác
    // sử dụng từ khóa này từ cùng một lớp
    Main()
    {
        // gọi hàm tạo 2
        this(5);
        System.out.println("Hàm tạo mặc định");
    }
    // phương thức khởi tạo được tham số hóa 2
    Main(int x)
    {
        // gọi hàm tạo 3
        this(5, 15);
        System.out.println(x);
    }
    // phương thức khởi tạo được tham số hóa 3
    Main(int x, int y)
    {
        System.out.println(x * y);
    }
    public static void main(String args[])
    {
        // gọi hàm tạo mặc định trước
        new Main();
    }
}

Kết quả

75
5
Hàm tạo mặc định

4. Tại sao cần sử dụng Constructor Chaining

Quá trình này được sử dụng khi chúng ta muốn thực hiện nhiều tác vụ trong một hàm tạo duy nhất thay vì tạo mã cho từng tác vụ trong một hàm tạo duy nhất. Chúng ta tạo một hàm tạo riêng cho từng tác vụ và làm cho chuỗi của chúng khiến chương trình dễ đọc hơn.

5. Constructor Chaining trong cùng một lớp

Constructor Chaining trong cùng một lớp bằng cách sử dụng từ khóa this(). Đồng thời ta phải tuân thủ một số quy tắc sau:

  • Biểu thức this() phải luôn là dòng đầu tiên của hàm tạo.
  • Ít nhất phải có một hàm tạo không có từ khóa this() (hàm tạo 3 trong ví dụ dưới đây).
  • Chuỗi xây dựng có thể đạt được theo bất kỳ thứ tự nào.

Ví dụ:

// Chương trình Java để minh họa Constructor Chaining
// trong cùng một lớp Sử dụng từ khóa this ()
class Main
{
    // hàm tạo mặc định 1
    // hàm tạo mặc định sẽ gọi một hàm tạo khác
    // sử dụng từ khóa này từ cùng một lớp
    Main()
    {
        // gọi hàm tạo 2
        this(9);
        System.out.println("Hàm tạo mặc định");
    }
    // phương thức khởi tạo được tham số hóa 2
    Main(int x)
    {
        // gọi hàm tạo 3
        this(9, 15);
        System.out.println(x);
    }
    // phương thức khởi tạo được tham số hóa 3
    Main(int x, int y)
    {
        System.out.println(x * y);
    }
    public static void main(String args[])
    {
        // gọi hàm tạo mặc định trước
        new Main();
    }
}

Kết quả

135
9
Hàm tạo mặc định

Vậy câu hỏi được đặt ra là điều gì xảy ra nếu chúng ta thay đổi thứ tự của các hàm tạo? Thực ra không có gì xảy ra. Chuỗi Constructor có thể đạt được theo bất kỳ thứ tự nào.

Ví dụ:

class Main
{
    Main()
    {
        System.out.println("default");
    }
    Main(int x)
    {
        this();
        System.out.println(x);
    }
    Main(int x, int y)
    {
        this(5);
        System.out.println(x * y);
    }

    public static void main(String args[])
    {
        new Main(8, 10);
    }
}

Kết quả

default
5
80

Trong ví dụ đầu, phương thức khởi tạo mặc định được gọi ở cuối. Nhưng trong ví dụ 2, phương thức khởi tạo mặc định được gọi đầu tiên. Do đó, thứ tự trong chuỗi hàm tạo không quan trọng.

6. Constructor Chaining đến lớp khác

Ta có thể Constructor Chaining đến lớp khác bằng cách sử dụng từ khóa super(). Và tương tự như chuỗi hàm tạo trong cùng một lớp, super() phải là dòng đầu tiên của hàm tạo vì hàm tạo của lớp siêu được gọi trước hàm tạo của lớp con.

Ví dụ:

// Chương trình Java để minh họa Constructor Chaining đến
// lớp khác sử dụng từ khóa super ()
class Base
{
    String name;
    // constructor 1
    Base()
    {
        this("");
        System.out.println("Hàm tạo không đối số của" +
                                        " lớp cơ sở");
    }
    // constructor 2
    Base(String name)
    {
        this.name = name;
        System.out.println("Gọi hàm tạo được tham số hóa"
                                            + " của cơ sở");
    }
}
class Derived extends Base
{
    // constructor 3
    Derived()
    {
        System.out.println("Hàm tạo không đối số " + "của nguồn gốc");
    }
    // phương thức khởi tạo được tham số hóa 4
    Derived(String name)
    {
        // gọi phương thức khởi tạo lớp cơ sở 2
        super(name);
        System.out.println("Gọi được tham số hóa " + "hàm tạo của có nguồn gốc");
    }
    public static void main(String args[])
    {
        // gọi hàm tạo được tham số hóa 4
        Derived obj = new Derived("test");

        // Gọi hàm tạo không đối số
        // Derived obj = new Derived ();
    }
}

Kết quả

Gọi hàm tạo được tham số hóa của cơ sở
Gọi được tham số hóa hàm tạo của có nguồn gốc

7. Sử dụng khối Init

Khi chúng ta muốn một số tài nguyên chung nhất định được thực thi với mọi phương thức khởi tạo, chúng ta có thể đặt mã vào khối Init . Khối Init luôn được thực thi trước bất kỳ hàm tạo nào, bất cứ khi nào một hàm tạo được sử dụng để tạo một đối tượng mới.

Ví dụ:

class Temp
{
    // khối được thực thi trước bất kỳ hàm tạo nào.
    {
        System.out.println("init block");
    }

    // hàm tạo no-arg
    Temp()
    {
        System.out.println("default");
    }

    // hàm tạo với một đối số.
    Temp(int x)
    {
        System.out.println(x);
    }

    public static void main(String[] args)
    {
         // Tạo đối tượng bằng cách gọi no-đối số
        // constructor.
        new Temp();

        // Tạo đối tượng bằng cách gọi tham số hóa
        // hàm tạo với một tham số.
        new Temp(10);
    }
}

Kết quả

init block
default
init block
10