Java 8 – Lớp cục bộ

5/5 - (1 vote)

Lớp cục bộ (local class) là các lớp được định nghĩa trong một khối lệnh.

Thường thì chúng ta hay định nghĩa lớp cục bộ trong khối lệnh của một phương thức, một câu lệnh for hoặc một câu lệnh if. Ví dụ:

public class OuterClass {

    public void printMessage(String msg) {
        final String parent = "Outer Class";        

        class LocalClass {
            String msg;
            LocalClass(String msg) {
                this.msg = msg;
            }

            public void print() {
                System.out.println(this.msg + " from " + parent);
            }
        }
  
        LocalClass lc = new LocalClass(msg);
        lc.print();
    }

    public static void main(String[] args) {
        OuterClass oc = new OuterClass();
        oc.printMessage("Hello World");
    }
}

Trong đoạn code trên thì chúng ta có lớp OuterClass là lớp cha ngoài cùng, bên trong có phương thức printMessage(), trong phương thức này chúng ta định nghĩa lớp LocalClass có phương thức print(). Ở đây lớp LocalClass chính là một lớp cục bộ, vì được định nghĩa trong một khối lệnh.

Hello World from Outer Class

Các lớp cục bộ có thể truy xuất đến các phương thức và thuộc tính của lớp cha của nó, tuy nhiên với điều kiện là thuộc tính đó phải được khai báo với từ khóa final. Trong đoạn code trên phương thức print() của lớp LocalClass có thể đọc thuộc tính parent của lớp OuterClass là vì thuộc tính parent được khai báo là final.

Tuy nhiên, kể từ phiên bản Java 8 trở đi thì lớp cục bộ cũng có thể truy xuất đến các thuộc tính “gần như final” nữa, ở đây Java quy định thuộc tính “gần như final” là các thuộc tính không khai báo từ khóa final nhưng không bao giờ thay đổi giá trị sau khi đã được khai báo và khởi tạo.

Do đó trong đoạn code trên chúng ta có thể bỏ từ khóa final ở thuộc tính parent. Nhưng nếu chúng ta gán lại giá trị mới cho thuộc tính parent thì Java sẽ báo lỗi khi biên dịch.

public class OuterClass {

    public void printMessage(String msg) {
        String parent = "Outer Class";        

        class LocalClass {
            String msg;
            LocalClass(String msg) {
                parent = "Changed";
                this.msg = msg;
            }

            public void print() {
                System.out.println(this.msg + " from " + parent);
            }
        }
  
        LocalClass lc = new LocalClass(msg);
        lc.print();
    }

    public static void main(String[] args) {
        OuterClass oc = new OuterClass();
        oc.printMessage("Hello World");
    }
}

Trong đoạn code trên chúng ta bỏ từ khóa final cho biến parent, sau đó thay đổi giá trị của biến này trong phương thức khởi tạo của lớp LocalClass. Khi biên dịch thì Java sẽ thông báo lỗi:

local variables referenced from an inner class must be final or effectively final
     parent = "Changed";
     ^

Lớp cục bộ và lớp nội khá giống nhau vì chúng đều không thể khai báo và định nghĩa các thuộc tính và phương thức static. Lớp cục bộ được định nghĩa trong một phương thức static thì chỉ có thể truy xuất các thuộc tính static của lớp chứa phương thức đó. Nói chung là việc truy xuất các thuộc tính static của lớp cục bộ khá hạn chế.

Chúng ta cũng không thể định nghĩa interface trong một khối lệnh bởi vì vốn dĩ interface cũng là static rồi.

public class OuterClass {

    public void printMessage(String msg) {
        String parent = "Outer Class"; 

        class LocalClass {
            String msg;
            LocalClass(String msg) {
                parent = "Changed";
                this.msg = msg;
            }

            public void print() {
                System.out.println(this.msg + " from " + parent);
            }
 
            public void greetInEnglish() {
                interface HelloThere {
                    public void greet();
                }
                class EnglishHelloThere implements HelloThere {
                    public void greet() {
                        System.out.println("Hello ");
                    }
                }
                HelloThere myGreeting = new EnglishHelloThere();
                myGreeting.greet();
            }
        }
 
        LocalClass lc = new LocalClass(msg);
        lc.print();
    }

    public static void main(String[] args) {
        OuterClass oc = new OuterClass();
        oc.printMessage("Hello World");
    }
}

Đoạn code trên sẽ báo lỗi.

interface not allowed here
     interface HelloThere {
     ^

Ngoài ra chúng ta cũng không thể khai báo phương thức static trong một lớp cục bộ:

public class OuterClass {
    public void outerClassMethod() {
        class LocalClass {
            public static void doNothing() {
                //...
            }
 
            LocalClass() {
                //...   
            }
        }
    }

    public static void main(String[] args) {
        OuterClass oc = new OuterClass();
        oc.outerClassMethod();
    }
}

Đoạn code trên sẽ báo lỗi:

Illegal static declaration in inner class LocalClass
     public static void doNothing() {
                        ^

Tuy nhiên có một điều kì dị là Java cho phép chúng ta khai báo một thuộc tính final static trong một lớp cục bộ:

public class OuterClass {

    public void outerClassMethod() {
        class LocalClass {
            public static final float PI = 3.14159f;
            LocalClass() {
                //...
            }
        }
    }

    public static void main(String[] args) {
        OuterClass oc = new OuterClass();
        oc.outerClassMethod();
    }
}
0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Inline Feedbacks
View all comments
Phạm Quang Linh
Phạm Quang Linh
6 năm trước

Bài viết rất tuyệt ạ, rất mong ad sớm ra nốt những phần còn lại. Gửi đến ad sự cảm kích và mến mộ