NỘI DUNG BÀI VIẾT
Constructor trong Java được sử dụng để tạo instance trong Java. Constructor gần như tương đương với các phương thức ngoại trừ 2 điều – tên của constructor giống với tên class và không có kiểu trả về.Đôi khi các hàm tạo cũng được coi là các phương thức đặc biệt để khởi tạo một đối tượng. Đôi khi các constructor cũng được coi là các phương thức đặc biệt để khởi tạo một đối tượng.
Constructor trong Java
Bất cứ khi nào chúng ta sử dụng từ khóa new để tạo instance của một class. thì hàm tạo được gọi và đối tượng được trả về. Vì phương thức khởi tạo chỉ có thể trả về đối tượng cho lớp, nó được thực hiện một cách ngầm định bởi thời gian chạy java và chúng ta không nên thêm kiểu trả về cho nó.
Nếu chúng ta thêm một kiểu trả về vào một phương thức khởi tạo, thì nó sẽ trở thành một phương thức của class. Đây là cách thời gian chạy java phân biệt giữa phương thức bình thường và phương thức khởi tạo. Giả sử chúng ta có đoạn code sau trong lớp Employee.
public Employee() {
System.out.println("Employee Constructor");
}
public Employee Employee() {
System.out.println("Employee Method");
return new Employee();
}
Code language: PHP (php)
Ở đây cái đầu tiên là một hàm tạo, hãy lưu ý rằng không có kiểu trả về và không có câu lệnh trả về. Phương thức thứ hai là một phương thức bình thường trong đó chúng ta lại gọi phương thức khởi tạo đầu tiên để lấy instance của Employee và trả về nó. Bạn không nên đặt tên phương thức giống với tên lớp vì nó tạo ra sự nhầm lẫn.
Các kiểu Constructor trong Java.
Có 3 kiểu Constructor trong Java
- Default Constructor
- No-Args constructor
- Parameterized constructor
Hãy xem tất cả các loại phương thức khởi tạo này với các chương trình ví dụ.
Default Constructor trong Java
Không bắt buộc phải luôn cung cấp implementation phương thức khởi tạo trong mã lớp. Nếu tôi không cung cấp hàm tạo, thì Java sẽ cung cấp triển khai constructor mặc định để tôi sử dụng.
Chúng ta hãy xem xét một chương trình đơn giản trong đó constructor mặc định đang được sử dụng vì chúng ta sẽ không xác định rõ ràng một constructor.
public class Data {
public static void main(String[] args) {
Data d = new Data();
}
}
Code language: JavaScript (javascript)
- Constructor mặc định chỉ có vai trò là khởi tạo đối tượng và trả nó về mã gọi.
- Constructor mặc định luôn không có đối số và chỉ được cung cấp bởi trình biên dịch java khi không có hàm tạo hiện có nào được xác định.
- Hầu hết thời gian chúng ta đều ổn với chính phương thức khởi tạo mặc định vì các thuộc tính khác có thể được truy cập và khởi tạo thông qua các phương thức getter setter.
No-Args Constructor
Constructor không có bất kỳ đối số nào được gọi là no-args Constructor. Nó giống như ghi đè hàm tạo mặc định và được sử dụng để thực hiện một số công việc trước khi khởi tạo như kiểm tra tài nguyên, kết nối mạng, ghi nhật ký, v.v. Hãy xem nhanh no-args Constructor trong java.
public class Data {
//no-args constructor
public Data() {
System.out.println("No-Args Constructor");
}
public static void main(String[] args) {
Data d = new Data();
}
}
Code language: PHP (php)
Bây giờ khi chúng ta gọi new Data(), thì phương thức khởi tạo no-args của chúng ta sẽ được gọi. Hình ảnh dưới đây minh họa hành vi này, hãy kiểm tra đầu ra bảng điều khiển của chương trình.
Parameterized Constructor
Hàm tạo với các đối số được gọi là hàm tạo tham số hóa. Hãy xem ví dụ về hàm tạo được tham số hóa trong java.
public class Data {
private String name;
public Data(String n) {
System.out.println("Parameterized Constructor");
this.name = n;
}
public String getName() {
return name;
}
public static void main(String[] args) {
Data d = new Data("Java");
System.out.println(d.getName());
}
}
Code language: JavaScript (javascript)
Constructor Overloading trong Java
Khi chúng ta có nhiều hơn một constructor, thì đó là constructor overloading trong Java. Hãy xem một ví dụ về constructor overloading trong chương trình Java sau:
public class Data {
private String name;
private int id;
//no-args constructor
public Data() {
this.name = "Default Name";
}
//one parameter constructor
public Data(String n) {
this.name = n;
}
//two parameter constructor
public Data(String n, int i) {
this.name = n;
this.id = i;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "ID="+id+", Name="+name;
}
public static void main(String[] args) {
Data d = new Data();
System.out.println(d);
d = new Data("Java");
System.out.println(d);
d = new Data("Pankaj", 25);
System.out.println(d);
}
}
Code language: JavaScript (javascript)
Private Constructor trong Java
Lưu ý rằng chúng ta không thể sử dụng các từ khóa abstract. final, static và synchronized cùng với constructor/ Tuy nhiên chúng ta có thể sử dụng access modifiers để kiểm soát việc khởi tạo đối tượng của class. Sử dụng public hoặc default vẫn ok, nhưng việc đặt một constructor là private thì có lợi ích gì? Trong trường hợp đó, bất kỳ class nào khác sẽ không thể tạo instance của class.
Well, một constructor được đặt ở chế độ private trong trường hợp chúng ta muốn implement singleton design pattern. Vì Java tự động cung cấp constructor default, chúng ta phải tạo một cách rõ ràgn một constructor và giữ nó ở chế độ private. Các class client được cung cấp một phươn gtức static để lấy instance của class.
Dưới đây là một ví dụ về constuctor private cho class Data.
// private constructor
private Data() {
//empty constructor for singleton pattern implementation
//can have code to be used inside the getInstance() method of class
}
Code language: PHP (php)
Constructor Chaining trong Java
Khi một constuctor gọi một constuctor khác trong cùng class, nó được gọi là constuctor chaining. Chúng ta sử dụng từ khóa this để gọi constructor khác trong class. Thỉnh thoảng thì nó được sử dụng để set một số value default trong class variables.
Lưu ý rằng một lệnh gọi hàm tạo khác phải là câu lệnh đầu tiên trong khối mã. Ngoài ra, không nên gọi đệ quy sẽ tạo ra một vòng lặp vô hạn. Hãy xem một ví dụ về constructor chaining trong chương trình java.
public class Employee {
private int id;
private String name;
public Employee() {
this("John Doe", 999);
System.out.println("Default Employee Created");
}
public Employee(int i) {
this("John Doe", i);
System.out.println("Employee Created with Default Name");
}
public Employee(String s, int i) {
this.id = i;
this.name = s;
System.out.println("Employee Created");
}
public static void main(String[] args) {
Employee emp = new Employee();
System.out.println(emp);
Employee emp1 = new Employee(10);
System.out.println(emp1);
Employee emp2 = new Employee("Pankaj", 20);
System.out.println(emp2);
}
@Override
public String toString() {
return "ID = "+id+", Name = "+name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Code language: JavaScript (javascript)
Tôi đã ghi đã method toString() để print một số thông tin hữu ích về đối tượng Employee. Dưới đây là kết quả được tạo ra bởi chương trình trên.
Employee Created
Default Employee Created
ID = 999, Name = John Doe
Employee Created
Employee Created with Default Name
ID = 10, Name = John Doe
Employee Created
ID = 20, Name = Pankaj
Code language: PHP (php)
Lưu ý cách một constructor đang được gọi từ một constructor khác, đó là quy trình constructor chaining.
Java Super Constructor
Đôi khi một class được kế thừa từ lớp cha, trong trường hợp đó, nếu chúng ta phải gọi constuctor cha thì chúng ta có thể sử dụng từ khóa super. Hãy cùng xem một ví dụ về việc sử dụng super class constructor.
Lưu ý rằng lệnh gọi constructor ở class cha phải là câu lệnh đầu tiên trong constructor class con. Ngoài ra, khi khởi tạo phương thức khởi tạo class con, Java đầu tiên khởi tạo class cha và sau đó là class con. Vì vậy, nếu super class constructor không được gọi một cách rõ ràng thì phương thức khởi tạo mặc định hoặc no-args được gọi bằng thời gian chạy Java. Hãy hiểu những khái niệm này thông qua ví dụ sau đây.
Giả sử chúng ta có hai class dưới đây:
public class Person {
private int age;
public Person() {
System.out.println("Person Created");
}
public Person(int i) {
this.age = i;
System.out.println("Person Created with Age = " + i);
}
}
Code language: PHP (php)
public class Student extends Person {
private String name;
public Student() {
System.out.println("Student Created");
}
public Student(int i, String n) {
super(i); // super class constructor called
this.name = n;
System.out.println("Student Created with name = " + n);
}
}
Code language: JavaScript (javascript)
Bây giờ nếu chúng ta tạo một object Student:
Student st = new Student();
Code language: JavaScript (javascript)
Output:
Person Created
Student Created
Vì vậy, lệnh gọi được chuyển đến constuctor no-args của class Student vì không có lệnh gọi super nào trong câu lệnh đầu tiên mà constuctor no-args hoặc constructor default của class Person được gọi. Điều gì sẽ xảy ra nếu chúng ta truyền tham số vào khi tạo mớ class Student là Student st = new Student(34, “HDD”);. output sẽ là:
Person Created with Age = 34
Student Created with name = HDD
Code language: JavaScript (javascript)
Ở đây output rõ ràng vì chúng ta đang gọi super constructor một cách rõ ràng, vì vậy Java không cần thực hiện thêm bất kỳ công việc nào nữa.
Trên đây là những điều về Constructor trong Java.
Happy learning!!!