Lớp lồng nhau trong java (Java inner class) – GP Coder (Lập trình Java)

Lớp lồng nhau (inner class) trong java là một lớp được khai báo trong lớp (class) hoặc interface khác.

Chúng ta sử dụng inner class để nhóm những lớp và những interface một cách logic lại với nhau ở một nơi để giúp cho code dễ đọc và dẽ bảo dưỡng hơn .Thêm vào đó, nó hoàn toàn có thể truy vấn toàn bộ những thành viên của lớp bên ngoài ( outer class ) gồm có những thành viên tài liệu private và phương pháp .

Cú pháp:


class Java_Outer_class {
	// code
	class Java_Inner_class {
		// code
	}
}

Các ưu điểm của inner class trong java :

  • Inner class biển diễn cho một kiểu đặc biệt của mối quan hệ đó là nó có thể truy cập tất cả các thành viên (các thành viên dữ liệu và các phương thức) của lớp ngoài bao gồm cả private.
  • Inner class được sử dụng để giúp code dễ đọc hơn và dễ bảo trì bởi vì nó nhóm các lớp và các interface một cách logic vào trong một nơi.
  • Code được tối ưu hóa: tiết kiệm code hơn.

Các kiểu của lớp lồng nhau trong java:

Lớp lồng nhau non-static ( inner class ) :

  • Member Inner Class: Một lớp được tạo ra bên trong một lớp và bên ngoài phương thức.
  • Annomynous Inner Class: Một lớp được tạo ra để implements interface hoặc extends class. Tên của nó được quyết định bởi trình biên dịch java.
  • Local Inner Class: Một lớp được tạo ra bên trong một phương thức.

Lớp lồng nhau Static :

  • Member Inner Class: Một lớp được tạo ra bên trong một lớp và bên ngoài phương thức.
  • Anonymous Inner Class: Một lớp được tạo ra để implements interface hoặc extends class. Tên của nó được quyết định bởi trình biên dịch java.
  • Local Inner Class: Một lớp được tạo ra bên trong một phương thức.
  • Static Nested Class: Một lớp static được tạo ra bên trong một lớp.
  • Nested Interface: Một interface được tạo ra bên trong một lớp hoặc một interface.

Member inner class trong java

Một lớp non-static được tạo ra bên trong một lớp nhưng ngoài một phương pháp được gọi là thành viên bên trong lớp hay thành viên inner class trong java .Cú pháp :


class Outer {
	// code
	class Inner {
		// code
	}
}

Ví dụ :

class MemberOuterExample {
	private int data = 30;

	class Inner {
		void msg() {
			System.out.println("data is " + data);
		}
	}

	public static void main(String args[]) {
		MemberOuterExample obj = new MemberOuterExample();
		MemberOuterExample.Inner in = obj.new Inner();
		in.msg();
	}
}

Kết quả khi chạy chương trình trên :

data is 30

Hoạt động nội bộ của member inner class trong java

Trình biên dịch java tạo ra hai file. class trong trường hợp của inner class. Tên của file của lớp bên trong là “ Outer $ Inner ”. Nếu bạn muốn tạo ra bộc lộ của lớp bên trong, bạn phải tạo ra bộc lộ của lớp bên ngoài. Trong trường hợp này, biểu lộ của lớp bên trong được tạo ra bên trong biểu lộ của lớp bên ngoài .

Code nội bộ được tạo ra bởi trình biên dịch

Trình biên dịch java tạo ra một file. class tên là MemberOuterExample $ Inner trong trường hợp này. Các thành viên inner class có tham chiếu của lớp bên ngoài MemberOuterExample đó là nguyên do tại sao nó hoàn toàn có thể truy vấn tổng thể những thành viên tài liệu của lớp MemberOuterExample gồm có cả private .


import java.io.PrintStream;

class MemberOuterExample$Inner {
    final MemberOuterExample this$0;

    MemberOuterExample$Inner() {
        super();
        this$0 = MemberOuterExample.this;
    }

    void msg() {
        System.out.println((new StringBuilder()).append("data is ")
            .append(MemberOuterExample.access$000(MemberOuterExample.this)).toString());
    }
}

Các file .class được trình biên dịch tạo ra khi thực hiện lệnh javac:

Xem thêm Hướng dẫn sử dụng plugin JadClipse để xem nội dung file .class.

Anonymous inner class trong java

Một lớp mà không có tên được gọi là lớp vô danh (anonymous inner class). Nó nên được sử dụng nếu bạn phải ghi đè phương thức của lớp hoặc interface. Anonymous inner class có thể được tạo ra bằng hai cách:

  • Class: có thể là abstract class hoặc class cụ thể.
  • Interface

Ví dụ về anonymous inner class với class


abstract class Person {
	abstract void eat();
}

class TestAnonymousInner {
	public static void main(String args[]) {
		Person p = new Person() {
			void eat() {
				System.out.println("nice fruits");
			}
		};
		p.eat();
	}
}

Kết quả thực thi chương trình trên :

nice fruits

Hoạt động nội bộ của đoạn code trên:

Person p = new Person() {
	void eat() {
		System.out.println("nice fruits");
	}
};
  • Một lớp được tạo ra nhưng tên của nó được quyết định bởi trình biên dịch mà extends lớp Person và cung cấp việc cài đặt phương thức eat().
  • Một đối tượng của lớp Anonymous được tạo ra mà được gọi bằng biến tham chiếu p của kiểu Person.

Lớp nội bộ được tạo ra bởi trình biên dịch :


import java.io.PrintStream;

static class TestAnonymousInner$1 extends Person {
    TestAnonymousInner$1() {
    }

    void eat() {
        System.out.println("nice fruits");
    }
}

Ví dụ về anonymous inner class với interface

interface Eatable {
	void eat();
}

class TestAnnonymousInner1 {
	public static void main(String args[]) {
		Eatable e = new Eatable() {
			public void eat() {
				System.out.println("nice fruits");
			}
		};
		e.eat();
	}
}

Kết quả khi thực thi chương trình trên :

nice fruits

Hoạt động nội bộ của đoạn code trên:

Eatable e = new Eatable() {
	public void eat() {
		System.out.println("nice fruits");
	}
};

Một lớp được tạo ra nhưng tên của nó được quyết định bởi trình biên dịch mà extends interface Eatable và cung cấp việc cài đặt phương thức eat().
Một đối tượng của lớp Anonymous được tạo ra mà được gọi bằng biến tham chiếu e của kiểu Eatable.

Lớp nội bộ được tạo ra bởi trình biên dịch:

import java.io.PrintStream;

static class TestAnonymousInner1$1 implements Eatable {
    TestAnonymousInner1$1() {
    }

    void eat() {
        System.out.println("nice fruits");
    }
}

Local inner class trong java

Một lớp được tạo ra bên trong một phương thức được gọi là local inner class. Nếu bạn muốn gọi các phương thức của lớp được khai báo bên trong một phương thức, bạn phải tạo ra thể hiện của lớp này bên trong phương thức chứa nó.


public class localInner1 {
	private int data = 30;// instance variable

	void display() {
		class Local {
			void msg() {
				System.out.println(data);
			}
		}
		Local l = new Local();
		l.msg();
	}

	public static void main(String args[]) {
		localInner1 obj = new localInner1();
		obj.display();
	}
}

Kết quả khi thực thi chương trình trên :

30

Lớp nội được tạo ra bởi trình biên dịch:

Trong trường hợp này, trình biên dịch sẽ tạo ra một lớp có tên LocalInner1 $ 1L ocal.class có tham chiếu của lớp bên ngoài ( LocalInner1 ) .

import java.io.PrintStream;

class LocalInner1$Local {
    final LocalInner1 this$0;

    LocalInner1$Local() {
        super();
        this$0 = Simple.this;
    }

    void msg() {
        System.out.println(LocalInner1.access$000(LocalInner1.this));
    }
}

Quy tắc cho biến local: Biến local không thể là private, public hoặc protected.

Các quy tắc cho Local Inner class

  • Local Inner class không thể được gọi từ một phương thức bên ngoài.
  • Local Inner class không thể truy cập biến local non-final từ JDK 1.7 trở vể trước. Kể từ JDK 1.8, có thể truy cập vào các biến local non-final trong lớp local inner class.
class localInner2 {
	private int data = 30; // instance variable

	void display() {
		int value = 50; // biến local phải là final từ jdk 1.7 trở về trước
		class Local {
			void msg() {
				System.out.println(value);
			}
		}
		Local l = new Local();
		l.msg();
	}

	public static void main(String args[]) {
		localInner2 obj = new localInner2();
		obj.display();
	}
}

Static nested class trong java

Một lớp static được tạo bên trong một lớp được gọi là lớp static lồng hay static nested class. Nó không thể truy cập các thành viên và phương thức non-static. Nó có thể được truy cập bởi tên lớp bên ngoài.

  • Nó có thể truy cập các thành viên dữ liệu tĩnh (static data members) của lớp ngoài bao gồm cả private.
  • Static nested class không thể truy cập thành viên dữ liệu hoặc phương thức non-static (instance).

Ví dụ về static nested class với thành viên tài liệu tĩnh ( static data members )

class TestOuter1 {
	static int data = 30;

	static class Inner {
		void msg() {
			System.out.println("data is " + data);
		}
	}

	public static void main(String args[]) {
		TestOuter1.Inner obj = new TestOuter1.Inner();
		obj.msg();
	}
}

Kết quả thực thi chương trình trên:

data is 30

Trong ví dụ này, tất cả chúng ta cần tạo ra bộc lộ lớp static lồng nhau, do tại nó có phương pháp instance msg ( ). Nhưng không cần phải tạo ra đối tượng người tiêu dùng lớp ngoài ( Outer class ) vì lớp lồng bên trong là static, những phương pháp hoặc những lớp hoàn toàn có thể được truy vấn mà không cần tạo đối tượng người dùng .

Lớp nội bộ được trình biên dịch tạo ra

import java.io.PrintStream;

static class TestOuter1$Inner {
    TestOuter1$Inner() {
    }

    void msg() {
        System.out.println((new StringBuilder()).append("data is ")
                .append(TestOuter1.data).toString());
    }
}

Ví dụ về static nested class với phương pháp tĩnh ( static method )

Nếu bạn có thành viên static bên trong lớp static lồng nhau, bạn không cần tạo ra bộc lộ của lớp tĩnh lồng nhau .

class TestOuter2 {
	static int data = 30;

	static class Inner {
		static void msg() {
			System.out.println("data is " + data);
		}
	}

	public static void main(String args[]) {
		TestOuter2.Inner.msg(); // Không cần tạo ra thể hiện của static nested class
	}
}

Interface lồng nhau ( nested interface ) trong java

Một interface được khai báo trong một interface hoặc lớp khác được gọi là interface lồng nhau hay nested interface.

Các interface lồng nhau được sử dụng để nhóm những interface tương quan để chúng hoàn toàn có thể thuận tiện được bảo dưỡng. Interface lồng nhau phải được phủ bọc bên ngoài bởi interface hoặc lớp. Nó không hề truy vấn trực tiếp .Một số điểm cần chú ý quan tâm :

  • Interface lồng nhau (nested interface) phải public nếu nó được khai báo bên trong interface, nhưng nó có thể có bất kỳ access modifier nào nếu khai báo trong lớp.
  • Interface lồng nhau (nested interface) được khai báo static một cách hiển nhiên.

Nested interface bên trong interface

Cú pháp :


interface interface_name {
    // code
    interface nested_interface_name {
        // code
    }
}



Ví dụ:

Trong ví dụ này, tất cả chúng ta sẽ học cách khai báo interface lồng nhau và cách tất cả chúng ta hoàn toàn có thể truy vấn nó .

interface Showable {
    void show();
 
    interface Message {
        void msg();
    }
}
 
class TestNestedInterface1 implements Showable.Message {
    public void msg() {
        System.out.println("Hello nested interface");
    }
 
    public static void main(String args[]) {
        Showable.Message message = new TestNestedInterface1(); // upcasting
        message.msg();
    }
}

Kết quả thực thi chương trình trên :

hello nested interface

Như bạn thấy trong ví dụ trên, tất cả chúng ta truy vấn interface Message bằng interface Showable bên ngoài của nó vì nó không hề được truy vấn trực tiếp. Trong khuôn khổ collection, mạng lưới hệ thống sun microsystem đã cung ứng một nested interface là Entry. Entry là subinterface của Map, nghĩa là được truy vấn bởi Map. Entry .

Code nội bộ được tạo ra bởi trình biên dịch java cho interface lồng nhau Message:

public static interface Showable$Message {
    public abstract void msg();
}

Nested interface bên trong class

Cú pháp :

class class_name {
    // code
    interface nested_interface_name {
        // code
    }
}

Ví dụ:

Hãy xem tất cả chúng ta hoàn toàn có thể định nghĩa một interface bên trong lớp như thế nào và tất cả chúng ta hoàn toàn có thể truy vấn nó như thế nào .

class A {
    interface Message {
        void msg();
    }
}
 
public class TestNestedInterface2 implements A.Message {
    public void msg() {
        System.out.println("Hello nested interface");
    }
 
    public static void main(String args[]) {
        A.Message message = new TestNestedInterface2();// upcasting
        message.msg();
    }
}

Kết quả thực thi chương trình trên :

hello nested interface

Chúng ta có thể định nghĩa một lớp bên trong interface?

Có, Nếu tất cả chúng ta xác lập một lớp bên trong interface, trình biên dịch java tạo ra một lớp static lồng nhau. Hãy xem tất cả chúng ta hoàn toàn có thể định nghĩa một lớp trong giao diện như thế nào :

interface M {
    class A {
    }
}

Tài liệu tham khảo

5.0

Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé!

Shares

Bình luận

phản hồi