Articles by "InnerClass"
Hiển thị các bài đăng có nhãn InnerClass. Hiển thị tất cả bài đăng
no image

Inner Class là gì?

Inner Class là một khái niệm chỉ về một lớp được khai báo bên trong lớp khác. Chúng ta sử dụng các Inner Class để nhóm các lớp và các Interface có quan hệ với nhau vào một vị trí để tăng tính đọc và tính duy trì.
Thêm vào đó, bạn có thể truy cập tất cả thành viên của Outer Class (lớp mà bao Inner Class), đó là: các thành viên dữ liệu và các phương thức private.

Cú pháp của Inner Class

class  Outer_class{  

// Day la phan code
class nner_class{
// Day la phan code
}
}

Lợi thế khi sử dụng Inner Class trong Java

Sử dụng Inner Class đem lại ba lợi thế chính là:
  • Inner Class biểu diễn một kiểu quan hệ đặc biệt, đó là: nó có thể truy cập tất cả các thành viên (thành viên dữ liệu và các phương thức) của Outer Class, bao gồm cả các thành viên được khai báo là private.
  • Inner Class được sử dụng để phát triển tính đọc và tính dễ dàng duy trì của code, bởi vì khi sử dụng Inner Class tức là bạn đã nhóm các lớp và các Interface có mối quan hệ với nhau vào một nơi.
  • Giúp tối ưu hóa code, tức là bạn có thể viết ít code hơn nhưng có thể mang lại hiệu quả tương tự.

Điểm khác nhau giữa Inner Class và Nested Class trong Java

Inner Class là một phần của Nested Class. Trong Nested Class, có hai loại là non-static và static. Các Nested Class mà không phải ở dạng static thì đó là Inner Class. Trong đó, loại Non-static Nested Class bao gồm:
  • Member Inner Class: là một lớp được tạo bên trong lớp và bên ngoài phương thức.
  • Anonymous Inner Class: là một lớp được tạo để triển khai (kế thừa) Interface hoặc kế thừa lớp. Tên của nó được quyết định bởi Compiler.
  • Local Inner Class: Một lớp được tạo bên trong phương thức.
Loại static Nested Class: một lớp static được tạo bên trong một lớp.
Nested Interface: là một Interface được tạo bên trong một lớp hoặc một Interface.
no image

Anonymous Inner Class là gì?

Một Inner Class được khai báo mà không kèm theo tên lớp được gọi là Anonymous Inner Class. Trong trường hợp như thế, chúng ta khai báo và khởi tạo chúng tại cùng một thời điểm. Nói chung, bạn nên sử dụng loại Inner Class này khi bạn muốn ghi đè phương thức của lớp hoặc Interface. Bạn theo dõi cú pháp sau để hiểu chi tiết hơn:

Cú pháp

// khai bao va khoi tao tai cung mot thoi diem
AnonymousInner inner_class = new AnonymousInner(){

public void phuong_thuc(){
// phan code cua phuong thuc
}
}; // ban chu y dau champ hay cuoi cung
Một Anonymous Inner Class có thể được tạo theo hai cách, đó là sử dụng các lớp (abstract hoặc concrete) hoặc các Interface.

Ví dụ Anonymous Inner Class trong Java

Trong ví dụ sau, mình sử dụng khái niệm Anonymous Inner Class trong khi ghi đè phương thức.
abstract class Cow {
abstract void drink();
}

class AnonymousInnerExample {
public static void main(String args[]) {

// phan code khai bao va khoi tao mot lop Inner Class
Cow p = new Cow() {
void drink() {
System.out.println("Cow likes drinking coffee!!!");
}
}; // phan ket thuc

p
.drink();
}
}
Chạy chương trình Java trên sẽ cho kết quả sau:
Cow likes drinking coffee!!!
Ở trên, tên của Anonymous Inner Class được quyết định bởi Compiler và nó sẽ kế thừa lớp Cow và cung cấp trình triển khai cụ thể của phương thức eat().
Tiếp đó, một đối tượng của Anonymous Inner Class được tạo và được tham chiếu bởi biến tham chiếu p của kiểu Cow.

Ví dụ tạo Anonymous Inner Class bởi sử dụng Interface trong Java

interface Drinkable {
void drink();
}

class AnonymousInnerExample {
public static void main(String args[]) {
Drinkable d = new Drinkable() {
public void drink() {
System.out.println("Cow likes drinking coffee!!!");
}
};
d
.drink();
}
}
Chạy chương trình Java trên sẽ cho kết quả sau:
Cow likes drinking coffee!!!

no image

Member Inner Class là gì ?

Một lớp không phải là static mà được tạo bên trong một lớp nhưng bên ngoài một phương thức thì được gọi là Member Inner Class.

Cú pháp

class  Outer_class{  

// Day la phan code
class Inner_class{
// Day la phan code
}
}

Ví dụ về Member Inner Class trong Java

Trong ví dụ sau, chúng ta tạo phương thức printMessage() trong Member Inner Class để truy cập thành viên dữ liệu static của Outer Class.
class MemberOuterExample {
private int exam = 30;
// khai bao Inner Class
class Inner {
void printMessage() {
System.out.println("Gia tri cua bien exam la: " + exam);
}
}
// phan ket thuc cua khai bao
public static void main(String args[]) {
MemberOuterExample obj = new MemberOuterExample();
MemberOuterExample.Inner in = obj.new Inner();
in.printMessage();
}
}
Chạy chương trình Java trên sẽ cho kết quả sau:
Gia tri cua bien exam la: 30

Tiến trình làm việc nội bộ của Member Inner Class trong Java

Khi xuất hiện Inner Class, Java Compiler tạo hai class file, trong đó tên class file của Inner Class sẽ ở dạng Outer$Inner. Nếu bạn muốn khởi tạo Inner Class, bạn phải tạo sự thể hiện (instance) của Outer Class. Trong trường hợp này, sự thể hiện của Inner Class được tạo bên trong sự thể hiện của Outer Class.
no image

Static Nested Class là gì?

Trong Java, một Static Class được tạo bên trong một lớp thì được gọi là Static Nested Class. Nó có thể truy cập các thành viên dữ liệu và phương thức non-static. Ngoài ra, nó có thể được truy cập bởi tên của Outer Class.

Ví dụ Static Nested Class với phương thức ở dạng non-static

class OuterClassExample {
static int example = 30;

static class Inner {
void printMessage() {
System.out.println("Gia tri cua bien example la: " + example);
}
}

public static void main(String args[]) {
OuterClassExample.Inner obj = new OuterClassExample.Inner();
obj
.printMessage();
}
}
Chạy chương trình Java trên sẽ cho kết quả:
Gia tri cua bien example la: 30
Trong ví dụ này, bạn cần tạo instance của Static Nested Class bởi vì phương thức printMessage() là phương thức dạng non-static. Nhưng bạn không cần tạo đối tượng của Outer Class bởi vì Nested Class là dạng static và các thuộc tính, phương thức hoặc các lớp cũng có thể được truy cập mà không cần sử dụng đối tượng.

Ví dụ Static Nested Class với phương thức ở dạng static

Nếu bạn có các thành viên static bên trong Static Nested Class, thì bạn không cần tạo instance của Static Nested Class mà vẫn có thể truy cập được các thành viên đó. Dưới đây là ví dụ:
class OuterClassExample {
static int example = 30;

static class Inner {
static void printMessage() {
System.out.println("Gia tri cua bien example la: " + example);
}
}

public static void main(String args[]) {
OuterClassExample.Inner.printMessage();// khong can tao instance cua static nested class
}
}
Nó sẽ cho kết quả sau:
Gia tri cua bien example la: 30
no image

Local Inner Class là gì?

Trong Java, một lớp được tạo bên trong một phương thức thì được gọi là Local Inner Class. Nếu bạn muốn triệu hồi các phương thức của Local Inner Class, bạn phải khởi tạo lớp này bên trong phương thức.
public class LocalInnerExample {
private int example = 30;// khoi tao bien

void display() {
// day la local inner class
class Local {
void printMessage() {
System.out.println("Gia tri cua bien example la: " +example);
}
}
// ket thuc local inner class
// truy cap local inner class
Local l = new Local();
l
.printMessage();
}

public static void main(String args[]) {
LocalInnerExample obj = new LocalInnerExample();
obj
.display();
}
}
Chạy chương trình Java trên sẽ cho kết quả:
Gia tri cua bien example la: 30

Một số qui tắc khi sử dụng Local Inner Class trong Java

  • Các biến cục bộ không thể là private, public, hoặc protected.
  • Local Inner Class không thể được triệu hồi ở bên ngoài phương thức.
  • Từ JDK 1.7 trở về trước, trong Local Inner Class, nếu bạn muốn truy cập biến cục bộ của phương thức, thì biến đó phải thuộc kiểu final. Còn bắt đầu từ JDK 1.8 trở đi, giới hạn này đã bị loại bỏ.

Ví dụ dưới đây minh họa cách sử dụng của Local Inner Class và biến cục bộ trong Java

class LocalInnerExample {
private int example = 30;// khoi tao bien

void display() {
final int value = 50;// neu bien khong phai thuoc dang final thi:
class Local {
void printMessage() {
System.out.println("Gia tri cua bien value la: " +value); // se cho Compiler Error tai dong nay
}
}
Local l = new Local();
l
.printMessage();
}

public static void main(String args[]) {
LocalInnerExample obj = new LocalInnerExample();
obj
.display();
}
}
Chạy chương trình Java trên sẽ cho kết quả:
Gia tri cua bien value la: 50
no image

Nested Interface là gì?

Một Interface mà được khai báo bên trong một Interface khác thì được gọi là Nested Interface. Tương tự như Inner Class, thì bạn sử dụng Nested Interface để nhóm các Interface có mối quan hệ với nhau để làm tăng tính đọc và giúp dễ dàng duy trì chúng hơn. Nested Interface phải được tham chiếu bởi Outer Interface hoặc bởi các lớp. Bạn không thể truy cập chúng một cách trực tiếp.

Một số điểm cần ghi nhớ về Nested Interface

  • Nested Interface phải là public nếu được khai báo bên trong Interface. Nhưng nếu nó được khai báo bên trong lớp thì bạn có thể sử dụng bất kỳ Modifier nào.
  • Theo ngầm định thì Nested Interface được khai báo là static.

Cú pháp của Nested Interface được khai báo bên trong Interface

interface outer_interface {
// phan khai bao code
interface nested_interface {
// phan khai bao code
}
}

Cú pháp của Nested Interface được khai báo bên trong lớp

class ten_lop{  
// phan code
interface nested_interface {
// phan khai bao code
}
}

Ví dụ với trường hợp khai báo bên trong Interface

Ví dụ sau minh họa cách khai báo và truy cập Nested Interface.
interface Showable {
void show();

interface Message {
void printMessage();
}
}

class NestedInterfaceExample implements Showable.Message {
public void printMessage() {
System.out.println("Hello nested interface!!!");
}

public static void main(String args[]) {
Showable.Message message = new NestedInterfaceExample();// tai day la dang upcasting
message
.printMessage();
}
}
Chạy chương trình Java trên sẽ cho kết quả:
Hello nested interface!!!
Như trong ví dụ trên, chúng ta có thể truy cập Message Interface bởi Outer Interface của nó là Showable bởi vì chúng ta không thể truy cập nó một cách trực tiếp. Việc này cũng giống như trường hợp chiếc điện thoại để trong phòng, chúng ta phải vào phòng thì mới lấy được nó. Trong Collection Framework, một ví dụ cho trường hợp Nested Interface là Entry. Entry là Interface con của Map, và để truy cập nó, chúng ta sử dụng cú pháp Map.Entry.

Ví dụ với trường hợp khai báo bên trong lớp

Ví dụ sau minh họa cách chúng ta định nghĩa một Interface bên trong một lớp và cách để truy cập nó.
class A {
interface Message {
void printMessage();
}
}

class NestedInterfaceExample implements A.Message {
public void printMessage() {
System.out.println("Hello nested interface!!!");
}

public static void main(String args[]) {
A
.Message message = new NestedInterfaceExample();// tai day la dang upcasting
message
.printMessage();
}
}
Chạy chương trình Java trên sẽ cho kết quả:
Hello nested interface!!!

Câu hỏi: Chúng ta có thể định nghĩa một lớp ở bên trong một Interface không?

Có, nếu bạn định nghĩa một lớp bên trong một Interface, thì Compiler sẽ tạo lớp đó là dạng Static Nested Class. Cú pháp như sau:
interface VietJack{  
class VietJackTeam{
}
}