|
| 1 | +// Tiếp tục về nội lớp. |
| 2 | +// 2. Nội lớp (inner class) còn có thể được định nghĩa trong một phương thức. |
| 3 | +/* |
| 4 | + * Quyền truy cập: |
| 5 | + * - Nội lớp có thể truy cập tất cả các biến và đối số của phương thức chứa nó. |
| 6 | + * - Nội lớp cũng có thể truy cập các thành viên của lớp chứa phương thức ấy. |
| 7 | + * Phạm vi sử dụng: Nội lớp chỉ có thể được sử dụng trong phương thức chứa nó. |
| 8 | + */ |
| 9 | + |
| 10 | +import java.util.ArrayList; |
| 11 | +import java.util.List; |
| 12 | + |
| 13 | +// Ví dụ: |
| 14 | + |
| 15 | +// Lớp Car đại diện cho một chiếc xe, bao gồm trạng thái của động cơ và mức nhiên liệu. |
| 16 | +// Chứa phương thức startEngine() để khởi động động cơ. |
| 17 | +class Car { |
| 18 | + private boolean engineRunning = false; |
| 19 | + private int fuelLevel = 0; |
| 20 | + |
| 21 | + public Car(int fuelLevel) { |
| 22 | + this.fuelLevel = fuelLevel; |
| 23 | + } |
| 24 | + |
| 25 | + public void startEngine() { |
| 26 | + // Nội lớp EngineStarter kiểm tra mức nhiên liệu trước khi khởi động động cơ. |
| 27 | + class EngineStarter { |
| 28 | + private void checkFuel() { |
| 29 | + if (fuelLevel <= 0) { |
| 30 | + throw new IllegalStateException("Cannot start engine: No fuel"); |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + private void initiateStartup() { |
| 35 | + engineRunning = true; |
| 36 | + System.out.println("Engine is now running."); |
| 37 | + } |
| 38 | + |
| 39 | + public void start() { |
| 40 | + checkFuel(); |
| 41 | + initiateStartup(); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + /* |
| 46 | + * - EngineStarter có thể truy cập các thành viên nội bộ của Car và ngược lại, |
| 47 | + * nhưng không gian bên ngoài không thể truy cập trực tiếp đến EngineStarter. |
| 48 | + * - EngineStarter làm cho việc khởi động động cơ trở nên riêng biệt với phần |
| 49 | + * còn lại của lớp Car, giúp giảm sự phức tạp của phương thức startEngine() và |
| 50 | + * tập trung vào một nhiệm vụ cụ thể. |
| 51 | + */ |
| 52 | + |
| 53 | + EngineStarter starter = new EngineStarter(); |
| 54 | + starter.start(); |
| 55 | + } |
| 56 | + |
| 57 | + public boolean isEngineRunning() { |
| 58 | + return engineRunning; |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +public class WithinMethods { |
| 63 | + public static void main(String[] args) { |
| 64 | + Car myCar = new Car(10); // Khởi tạo xe với 10 đơn vị nhiên liệu |
| 65 | + myCar.startEngine(); // Khởi động động cơ |
| 66 | + System.out.println("Is the engine running? -> " + myCar.isEngineRunning()); |
| 67 | + |
| 68 | + Car anotherCar = new Car(0); // Khởi tạo xe với 0 đơn vị nhiên liệu |
| 69 | + anotherCar.startEngine(); // Khởi động động cơ |
| 70 | + System.out.println("Is the engine running? -> " + anotherCar.isEngineRunning()); |
| 71 | + // -> IllegalStateException: Cannot start engine: No fuel |
| 72 | + |
| 73 | + System.out.println("--------------------------------------------------"); |
| 74 | + |
| 75 | + EventNotifier notifier = new EventNotifier(); |
| 76 | + notifier.addUser("Alice"); |
| 77 | + notifier.addUser("Bob"); |
| 78 | + |
| 79 | + // Gửi thông điệp |
| 80 | + notifier.notifyUsers("System will be down for maintenance tonight."); |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +// Có một số hạn chế khi sử dụng nội lớp trong phương thức: |
| 85 | +/* |
| 86 | + * - Thời gian sống của biến: Khi một phương thức kết thúc, các biến địa phương |
| 87 | + * (local) của nó thường biến mất. Tuy nhiên, bất kỳ đối tượng nào được tạo ra |
| 88 | + * trong phương thức, bao gồm các instance của nội lớp vẫn tồn tại cho đến khi |
| 89 | + * chúng không còn được tham chiếu. Điều này dẫn đến, bất kỳ biến địa phương nào |
| 90 | + * được sử dụng trong nội lớp cũng phải tồn tại sau khi phuơng thức kết thúc. |
| 91 | + * -> Để đảm bảo các biến địa phương có thể được sử dụng an toàn bởi nội lớp sau |
| 92 | + * khi phương thức kết thúc, chúng phải được khai báo là final hoặc effectively |
| 93 | + * final. |
| 94 | + */ |
| 95 | + |
| 96 | +// Ví dụ khác: |
| 97 | + |
| 98 | +// Lớp EventNotifier thông báo một thông điệp cụ thể đến một danh sách người |
| 99 | +// dùng. |
| 100 | +class EventNotifier { |
| 101 | + private List<String> userList = new ArrayList<>(); |
| 102 | + |
| 103 | + // Phương thức thêm người dùng vào danh sách thông báo |
| 104 | + public void addUser(String user) { |
| 105 | + userList.add(user); |
| 106 | + } |
| 107 | + |
| 108 | + // Phương thức thông báo người dùng với một thông điệp cụ thể |
| 109 | + public void notifyUsers(final String message) { |
| 110 | + // Inner class để gửi thông báo |
| 111 | + class Notifier { |
| 112 | + // Phương thức gửi thông điệp |
| 113 | + public void sendNotification() { |
| 114 | + for (String user : userList) { |
| 115 | + System.out.println("Notifying " + user + ": " + message); |
| 116 | + } |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + // Tạo một instance của inner class và sử dụng nó |
| 121 | + Notifier notifier = new Notifier(); |
| 122 | + notifier.sendNotification(); |
| 123 | + } |
| 124 | +} |
0 commit comments