Java OOP – Phương thức khởi tạo, setter, getter

Constructor trong java

Constructor trong java là một dạng đặc biệt của phương thức được sử dụng để khởi tạo các đối tượng.

Java Constructor được gọi tại thời điểm tạo đối tượng. Nó khởi tạo các giá trị để cung cấp dữ liệu cho các đối tượng, đó là lý do tại sao nó được gọi là constructor.

Các quy tắc tạo constructor trong java

Có 2 quy tắc cơ bản cho việc tạo constructor:

  1. Tên constructor phải giống tên lớp chứa nó.
  2. Constructor không có kiểu trả về tường minh.

Các kiểu của java constructor

Có 2 kiểu của constructor

  1. Constructor mặc định (không có tham số truyền vào)
  2. Constructor tham số
các kiểu constructor trong java

Constructor mặc định trong java

Một constructor mà không có tham số được gọi là constructor mặc định.

Cú pháp của constructor mặc định:

<class_name>() {
    // code
}  

Ví dụ về constructor mặc định:

class Bike1 {  
    Bike1() {
        System.out.println("Bike is created");
    }  
    public static void main(String args[]) {  
       Bike1 b=new Bike1();  
    }  
}  

Output:

Bike is created
Constructor mặc định cung cấp các giá trị mặc định như 0, null, (tùy thuộc vào kiểu dữ liệu) ... tới đối tượng được khởi tạo.

Ví dụ:
class Student3{  
    int id;  
    String name;  
   
    void display() {
        System.out.println(id+" "+name);
    }  
   
    public static void main(String args[]) {
        Student3 s1=new Student3();  
        Student3 s2=new Student3();  
        s1.display();  
        s2.display();  
    }  
}  
Output:

0 null
0 null

Giải thích: Trong ví dụ trên, bạn không tạo bất kỳ constructor nào, vì vậy trình biên dịch tự động tạo một constructor mặc định cho bạn. Giá trị 0 và null được cung cấp bởi constructor mặc định đó.

Constructor tham số trong java

Một constructor có tham số truyền vào được gọi là constructor tham số.

Constructor tham số được sử dụng để cung cấp các giá trị khác nhau cho các đối tượng khác nhau.

Ví dụ:

class Student4{  
    int id;  
    String name;  
       
    Student4(int i,String n) {  
        id = i;  
        name = n;  
    }  
    void display() {
        System.out.println(id+" "+name);
    }  
    
    public static void main(String args[]) {  
        Student4 s1 = new Student4(111,"Viet");  
        Student4 s2 = new Student4(222,"Tuts");  
        s1.display();  
        s2.display();  
   }  
}  

Output:

111 Viet
222 Tuts

Constructor Overloading trong java

Constructor Overloading là một kỹ thuật trong Java. Bạn có thể tạo nhiều constructor trong cùng một lớp với danh sách tham số truyền vào khác nhau. Trình biên dịch phân biệt các constructor này thông qua số lượng và kiểu của các tham số truyền vào.

Ví dụ:

class Student5 {
 int id;
 String name;
 int age;
 
 Student5(int i, String n) {
  id = i;
  name = n;
 }
 
 Student5(int i, String n, int a) {
  id = i;
  name = n;
  age = a;
 }
 
 void display() {
  System.out.println(id + " " + name + " " + age);
 }
 
 public static void main(String args[]) {
  Student5 s1 = new Student5(111, "Viet");
  Student5 s2 = new Student5(222, "Tuts", 25);
  s1.display();
  s2.display();
 }
}

Output:

111 Viet 0
222 Tuts 25

Sự khác nhau giữa constructor và phương thức trong java

ConstructorPhương thức
Constructor được sử dụng để khởi tạo trạng thái của một đối tượng.Phương thức được sử dụng để thể hiện hành động của một đối tượng.
Constructor không có kiểu trả về.Phương thức có kiểu trả về.
Constructor được gọi ngầm.Phương thức được gọi tường minh.
Trình biên dịch Java tạo ra constructor mặc định nếu bạn không có constructor nào.Phương thức không được tạo ra bởi trình biên dịch Java.
Tên của constructor phải giống tên lớp.Tên phương thức có thể giống hoặc khác tên lớp.

Từ khóa this trong java là một biến tham chiếu được sử dụng để tham chiếu tới đối tượng của lớp hiện tại.

Trong java, Từ khóa this có 6 cách sử dụng như sau:

  1. Từ khóa this có thể được dùng để tham chiếu tới biến instance của lớp hiện tại.
  2. this() có thể được dùng để gọi Constructor của lớp hiện tại.
  3. Từ khóa this có thể được dùng để gọi phương thức của lớp hiện tại.
  4. Từ khóa this có thể được truyền như một tham số trong phương thức.
  5. Từ khóa this có thể được truyền như một tham số trong phương Constructor.
  6. Từ khóa this có thể được dùng để trả về instance của lớp hiện tại.

1. Tham chiếu tới biến instance của lớp hiện tại.

Từ khóa this trong java có thể được dùng để tham chiếu tới biến instance của lớp hiện tại.

Nếu có sự trùng tên nhau giữa biến toàn cục và tham số khiến bạn bị phân vân. Từ khóa this sẽ giúp bạn giải quyết sự phân vân của bạn.

Bạn sẽ hiểu ra vấn đề nếu không dùng từ khóa this trong ví dụ sau:

public class Student10 {
    int id;
    String name;
 
    Student10(int id, String name) {
        id = id;
        name = name;
    }
 
    void display() {
        System.out.println(id + " " + name);
    }
 
    public static void main(String args[]) {
        Student10 s1 = new Student10(111, "Viet");
        Student10 s2 = new Student10(222, "Nam");
        s1.display();
        s2.display();
    }
}

Kết quả:

0 null 
0 null

Trong ví dụ trên, tên của tham số của Constructor Student10() trùng với tên của biến toàn cục đó là lý do tại sao cần phải sử dụng từ khóa this để phân biệt biến cục bộ và biến toàn cục.

Ví dụ dưới đây giải quyết vấn đề trên bằng cách sử dụng từ khóa this:

public class Student11 {
    int id;
    String name;
 
    Student11(int id, String name) {
        this.id = id;
        this.name = name;
    }
 
    void display() {
        System.out.println(id + " " + name);
    }
 
    public static void main(String args[]) {
        Student11 s1 = new Student11(111, "Viet");
        Student11 s2 = new Student11(222, "Nam");
        s1.display();
        s2.display();
    }
}

Kết quả:

111 Viet
222 Nam

Nếu biến cục bộ và biến toàn cục có tên khác nhau thì không cần sử dụng từ khóa this.

public class Student12 {
    int id;
    String name;
 
    Student12(int i, String n) {
        id = i;
        name = n;
    }
 
    void display() {
        System.out.println(id + " " + name);
    }
 
    public static void main(String args[]) {
        Student12 e1 = new Student12(111, "Viet");
        Student12 e2 = new Student12(222, "Nam");
        e1.display();
        e2.display();
    }
}

Kết quả:

111 Viet
222 Name

2. Sử dụng this() gọi Constructor của lớp hiện tại.

Phương thức this() có thể được sử dụng để gọi Constructor của lớp hiện tại. Cách sử dụng này sẽ hữu dụng hơn nếu bạn có nhiều Constructor trong một lớp và bạn muốn sử dụng lại Constructor.

Ví dụ:

public class Student13 {
    int id;
    String name;
 
    Student13() {
        System.out.println("call Constructor mặc định");
    }
 
    Student13(int id, String name) {
        this(); // nó được sử dụng để gọi Constructor của lớp hiện tại
        this.id = id;
        this.name = name;
    }
 
    void display() {
        System.out.println(id + " " + name);
    }
 
    public static void main(String args[]) {
        Student13 e1 = new Student13(111, "Viet");
        Student13 e2 = new Student13(222, "Nam");
        e1.display();
        e2.display();
    }
}

Kết quả:

call Constructor mặc định
call Constructor mặc định
111 Viet
222 Nam

Ví trí sử dụng this() để gọi Constructor

this() được dùng để sự dụng lại Constructor trong Constructor khác. Nó duy trì 1 chuỗi các Constructor.

Ví dụ:

public class Student14 {
    int id;
    String name;
    String city;
 
    Student14(int id, String name) {
        this.id = id;
        this.name = name;
    }
 
    Student14(int id, String name, String city) {
        this(id, name);// now no need to initialize id and name
        this.city = city;
    }
 
    void display() {
        System.out.println(id + " " + name + " " + city);
    }
 
    public static void main(String args[]) {
        Student14 e1 = new Student14(111, "Viet");
        Student14 e2 = new Student14(222, "Nam", "Ha Noi");
        e1.display();
        e2.display();
    }
}

Kết quả:

111 Viet null
222 Nam Ha Noi

Quy tắc: this() phải được khai báo dòng lệnh đầu tiên trong Constructor.

Ví dụ:

public class Student15 {
    int id;
    String name;
 
    Student15() {
        System.out.println("default Constructor is invoked");
    }
 
    Student15(int id, String name) {
        id = id;
        name = name;
        this();// must be the first statement
    }
 
    void display() {
        System.out.println(id + " " + name);
    }
 
    public static void main(String args[]) {
        Student15 e1 = new Student15(111, "karan");
        Student15 e2 = new Student15(222, "Aryan");
        e1.display();
        e2.display();
    }
}

Kết quả:

Compile Time Error

3. Gọi phương thức của lớp hiện tại.

Bạn có thể sử dụng từ khóa this để gọi phương thức của lớp hiện tại. Nếu bạn không sử dụng từ khóa this, trình biên dịch sẽ tự động thêm từ khóa this cho việc gọi phương thức.

su-dung-tu-khoa-this-trong-java-3

Hãy xem ví dụ sau để hiểu rõ hơn.

public class Example3 {
    void m() {
        System.out.println("Gọi phương thức bằng từ khóa this");
    }
 
    void n() {
        this.m();
    }
 
    void p() {
        n();// trình biên dịch sẽ thêm this để gọi phương thức n() như this.n()
    }
 
    public static void main(String args[]) {
        Example3 o1 = new Example3();
        o1.p();
    }
}

Kết quả:

Gọi phương thức bằng từ khóa this

4. Sử dụng từ khóa this như một tham số của phương thức.

Từ khóa this có thể được dùng như một tham số trong phương thức. Cách dùng này chủ yếu được sử dụng trong sử lý sự kiện.

Hãy xem ví dụ sau để hiểu rõ hơn.

public class Example4 {
    void m(Example4 obj) {
        System.out.println("Hello Java");
    }
 
    void p() {
        m(this);
    }
 
    public static void main(String args[]) {
        Example4 o1 = new Example4();
        o1.p();
    }
}

Kết quả:

Hello Java

Từ khóa this được sử dụng như một tham số trong việc xử lý sự kiện hoặc trong trường hơp mà chúng ta phải cung cấp tham chiếu của một lớp cho một lớp khác.


5. Sử dụng từ khóa this như một tham số của Constructor.

Bạn cũng có thể truyền từ khóa this trong Constructor. Tính năng này rất hữu ích nếu chúng ta phải sử dụng một đối tượng trong nhiều lớp.

Ví dụ:

class B {  
  A4 obj;  
  B(A4 obj) {  
    this.obj=obj;  
  }  
  void display() {  
    System.out.println(obj.data);// sử dụng biến thành viên cửa lớp A4
  }  
}  
   
class A4 {  
  int data=10;  
  A4(){  
   B b = new B(this);  
   b.display();  
  }  
  public static void main(String args[]) {  
   A4 a = new A4();  
  }  
}  

Kết quả:

10

6. Sử dụng từ khóa this để trả về instance của lớp hiện tại.

Chúng ta có thể trả về instance của lớp hiện tại bằng cách sử dụng từ khóa this. Trong trường hợp này, kiểu trả về của phương thức phải là kiểu class (không là kiểu nguyên thủy).

Ví dụ:

class A {  
    A getA() {  
        return this;  
    }  
    void msg() {
        System.out.println("Hello Java");
    }  
}  
   
class Test1 {  
    public static void main(String args[]) {  
        new A().getA().msg();  
    }  
}  

Kết quả:

Hello java

Ví dụ chứng minh rằng từ khóa this tham chiếu tới biến instance của lớp hiện tại. Chúng ta in biến tham chiếu và this, kết quả của chúng là giống nhau.

class A5 {
 void m() {
  System.out.println(this); //in ra cung tham chieu ID  
 }
 
 public static void main(String args[]) {
  A5 obj = new A5();
  System.out.println(obj); //in tham chieu ID  
 
  obj.m();
 }
}

Kết quả:

A5@22b3ea59
A5@22b3ea59

Từ khóa super trong java

Từ khóa super trong java là một biến tham chiếu được sử dụng để tham chiếu trực tiếp đến đối tượng của lớp cha gần nhất.

Bất cứ khi nào bạn tạo ra instance(thể hiển) của lớp con, một instance của lớp cha được tạo ra ngầm định, nghĩa là được tham chiếu bởi biến super.

Trong java, từ khóa super có 3 cách sử dụng như sau:

  1. Từ khóa super được sử dụng để tham chiếu trực tiếp đến biến instance của lớp cha gần nhất.
  2. super() được sử dụng để gọi trực tiếp Constructor của lớp cha.
  3. Từ khóa super được sử dụng để gọi trực tiếp phương thức của lớp cha.

1. Tham chiếu trực tiếp đến biến instance của lớp cha.

Từ khóa super được sử dụng để tham chiếu trực tiếp đến biến instance của lớp cha.

Ví dụ: khi không sử dụng từ khóa super

class Vehicle {
    int speed = 50;
}
 
 public class Bike extends Vehicle {
    int speed = 100;
 
    void display() {
        System.out.println(speed); //in speed của lớp Bike   
    }
 
    public static void main(String args[]) {
        Bike b = new Bike();
        b.display();
    }
}

Kết quả:

100

Ví dụ: khi sử dụng từ khóa super

class Vehicle {
    int speed = 50;
}
 
public class Bike2 extends Vehicle {
    int speed = 100;
 
    void display() {
        System.out.println(super.speed);//in speed của lớp Vehicle  
    }
 
    public static void main(String args[]) {
        Bike2 b = new Bike2();
        b.display();
 
    }
}

Kết quả:

50

2. Sử dụng super()

Trong java, super() được sử dụng để gọi trực tiếp Constructor của lớp cha.

class Vehicle {
    Vehicle() {
        System.out.println("Vehicle is created");
    }
}
 
class Bike2 extends Vehicle {
    Bike2() {
        super();//gọi Constructor của lớp cha  
        System.out.println("Bike is created");
    }
 
    public static void main(String args[]) {
        Bike2 b = new Bike2();
    }
}

Kết quả:

Vehicle is created
Bike is created

Note: super() được tự động thêm vào mỗi Constructor của class bởi trình biên dịch.

tu-khoa-super-trong-java-1

Như chúng ta đã biết Constructor được tạo ra tự động bởi trình biên dịch nhưng nó cũng thêm super() vào câu lệnh đầu tiên. Nếu bạn tạo Constructor và bạn không có this() hoặc super() ở dòng lệnh đầu tiên, trình biên dịch sẽ cung cấp super() của Constructor.

Một ví dụ khác của từ khóa super nơi super() được cung cấp ngầm định bởi trình biên dịch.

class Vehicle {
    Vehicle() {
        System.out.println("Vehicle is created");
    }
}
 
public class Bike6 extends Vehicle {
    int speed;
 
    Bike6(int speed) {
        this.speed = speed;
        System.out.println(speed);
    }
 
    public static void main(String args[]) {
        Bike6 b = new Bike6(10);
    }
}

Kết quả:

Vehicle is created
10

3. super được sử dụng để gọi trực tiếp phương thức của lớp cha.

Từ khóa super cũng có thể được sử dụng để gọi phương thức của lớp cha. Nó nên được sử dụng trong trường hợp lớp chứa các phương thức tương tự như lớp cha như trong ví dụ dưới đây:

class Person {
    void message() {
        System.out.println("welcome");
    }
}
 
public class Student16 extends Person {
    void message() {
        System.out.println("welcome to java");
    }
 
    void display() {
        message();// gọi phương thức message() của lớp hiện tại
        super.message();// gọi phương thức message() của lớp cha
    }
 
    public static void main(String args[]) {
        Student16 s = new Student16();
        s.display();
    }
}

Kết quả:

welcome to java
welcome

Trong ví dụ trên cả hai lớp Student và Person đều có phương thức message(). Nếu bạn gọi phương thức message() từ lớp Student thì phương thức message của Student sẽ đươc thực thi vì phương thức ở local sẽ được ưu tiên.

Trong TH không có phương thức ở class con giống class cha thì không cần phải sử dụng super. Ví dụ:

class Person {
    void message() {
        System.out.println("welcome");
    }
}
 
public class Student17 extends Person {
 
    void display() {
        message();// will invoke parent class message() method
    }
 
    public static void main(String args[]) {
        Student17 s = new Student17();
        s.display();
    }
}

Kết quả:

welcome