JavaRush /Blog Java /Random-VI /Bảng liệt kê trong Java (java enum)
articles
Mức độ

Bảng liệt kê trong Java (java enum)

Xuất bản trong nhóm
Khi lập trình, chúng ta thường gặp phải nhu cầu giới hạn tập hợp các giá trị hợp lệ cho một kiểu dữ liệu nhất định. Vì vậy, ví dụ, ngày trong tuần có thể có 7 giá trị khác nhau, tháng trong năm có thể có 12 và mùa có thể có 4. Để giải quyết những vấn đề như vậy, nhiều ngôn ngữ lập trình kiểu tĩnh cung cấp một kiểu dữ liệu đặc biệt - phép liệt kê ( enum). Việc liệt kê không xuất hiện ngay lập tức trong Java. Cấu trúc ngôn ngữ chuyên biệt enumđã được giới thiệu bắt đầu từ phiên bản 1.5. Cho đến thời điểm này, các lập trình viên đã sử dụng các phương pháp khác để thực hiện phép liệt kê. Bảng liệt kê trong Java (java enum) - 1

xây dựng enum

Hãy bắt đầu với một ví dụ. Hãy mô tả enumkiểu dữ liệu để lưu trữ phần bằng cách sử dụng:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Vâng, một ví dụ đơn giản về việc sử dụng nó:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
Kết quả là SUMMER sẽ được in ra bảng điều khiển . Tôi nghĩ rằng ví dụ này là hiển nhiên và không cần giải thích.

Enum là một lớp

Bằng cách khai báo enum, chúng ta ngầm tạo ra một lớp dẫn xuất từ java.lang.Enum​​. Thông thường, việc xây dựng enum Season { ... }tương đương với class Season extends java.lang.Enum { ... }. Và mặc dù trình biên dịch không cho phép chúng ta kế thừa một cách rõ ràng từ java.lang.Enumchúng ta, nhưng vẫn dễ dàng xác minh rằng enumnó được kế thừa bằng cách sử dụng reflection:
System.out.println(Season.class.getSuperclass());
Sau đây sẽ được hiển thị trên bảng điều khiển:
class java.lang.Enum
Việc kế thừa thực tế được trình biên dịch Java tự động thực hiện cho chúng ta. Tiếp theo, hãy đồng ý gọi lớp do trình biên dịch tạo ra để thực hiện phép liệt kê là enum-class, và các giá trị có thể có của kiểu liệt kê là enumcác phần tử -a.

Các thành viên Enum là các thể hiện enumcủa một -class có thể truy cập tĩnh

Các phần tử enum Season (WINTER, SPRING и т.д.)là các phiên bản có thể truy cập tĩnh enumcủa -class Season. Tính khả dụng tĩnh của chúng cho phép chúng tôi thực hiện so sánh bằng cách sử dụng toán tử so sánh tham chiếu ==. Ví dụ:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;

Tên và số sê-ri của phần tử enum

Như đã đề cập trước đó, bất kỳ enum-class nào cũng kế thừa java.lang.Enum, chứa một số phương thức hữu ích cho tất cả các kiểu liệt kê. Ví dụ:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
Đầu ra sẽ là:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
Các phương pháp name()toString()được hiển thị ở đây ordinal(). Ngữ nghĩa của các phương pháp là rõ ràng. Cần lưu ý rằng các phương thức này enumđược kế thừa từ lớp java.lang.Enum. Lấy một phần tử enumbằng cách biểu diễn chuỗi tên của nó Khá thường xuyên nảy sinh nhiệm vụ lấy một phần tử enumbằng cách biểu diễn chuỗi của nó. Với những mục đích này, trong mỗi enumlớp, trình biên dịch sẽ tự động tạo một phương thức tĩnh đặc biệt: public static EnumClass valueOf(String name), phương thức này trả về một phần tử liệt kê EnumClasscó tên bằng name. Ví dụ sử dụng:
String name = "WINTER";
Season season = Season.valueOf(name);
Kết quả của việc thực thi mã, biến mùa sẽ bằng Season.WINTER. Xin lưu ý rằng nếu không tìm thấy phần tử, ngoại lệ IllegalArgumentException sẽ được ném ra và nếu nó namebằng nhau null, ngoại lệ NullPointerException sẽ được ném ra . Nhân tiện, điều này thường bị lãng quên. Vì lý do nào đó, nhiều người tin chắc rằng nếu một hàm nhận một đối số và trong những điều kiện nhất định ném ra IllegalArgumentException thì khi chuyển nó đến đó , IllegalArgumentExceptionnull chắc chắn cũng sẽ được ném ra . Nhưng đó không phải là vấn đề. Tiếp tục đi. Lấy tất cả các phần tử của một bảng liệt kê Đôi khi bạn cần lấy danh sách tất cả các phần tử của một -class trong thời gian chạy. Với những mục đích này, trình biên dịch sẽ tạo một phương thức trong mỗi lớp -class . Ví dụ sử dụng: enumenumpublic static EnumClass[] values()
System.out.println(Arrays.toString(Season.values()));
Chúng tôi nhận được kết quả đầu ra sau:
[WINTER, SPRING, SUMMER, AUTUMN]
Lưu ý rằng cả phương thức valueOf()lẫn phương thức đều không values()được định nghĩa trong lớp java.lang.Enum. Thay vào đó, chúng được trình biên dịch tự động thêm vào khi enumlớp - được biên dịch. Thêm các phương thức của riêng bạn vào enum-class Bạn có cơ hội thêm các phương thức của riêng mình vào cả enum-class và các phần tử của nó: Bảng liệt kê trong Java (java enum) - 2Tương tự, nhưng có tính đa hình: Bảng liệt kê trong Java (java enum) - 3Ví dụ cuối cùng minh họa việc sử dụng tính kế thừa trong enum. Thêm về điều này sau. Tính kế thừaenum trong Java enumcho phép bạn triển khai hệ thống phân cấp lớp, các đối tượng của nó được tạo trong một phiên bản duy nhất và có thể truy cập tĩnh. Trong trường hợp này, các phần tử enumcó thể chứa hàm tạo của riêng chúng. Hãy đưa ra một ví dụ: Ở đây chúng tôi khai báo Bảng liệt kê trong Java (java enum) - 4một bảng liệt kê Typecó ba phần tử INTINTEGER. STRINGTrình biên dịch sẽ tạo các lớp và đối tượng sau:
  • Type- lớp bắt nguồn từjava.lang.Enum
  • INT- đối tượng của lớp 1 bắt nguồn từType
  • INTEGER- đối tượng của lớp 2 bắt nguồn từType
  • STRING- đối tượng của lớp thứ 3 bắt nguồn từType
Ba lớp dẫn xuất sẽ được tạo bằng phương thức đa hình Object parse(String)và hàm tạo Type(..., boolean). Đồng thời, các đối tượng của lớp INTvà tồn tại trong một bản sao duy INTEGERnhất STRINGvà có thể truy cập tĩnh. Bạn có thể xác minh điều này:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass()  + " " + Type.STRING.getClass().getSuperclass());
Chúng tôi nhận được kết quả đầu ra sau:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
Có thể thấy trình biên dịch đã tạo ra một lớp Typevà 3 nestedlớp dẫn xuất từ Type​​.

Lớp enum được dịch ngược có tính kế thừa

Để khẳng định điều trên, chúng tôi cũng trình bày kết quả dịch ngược bảng liệt kê Typetừ ví dụ trên: Bảng liệt kê trong Java (java enum) - 5

Bảng liệt kê và đa hình tham số

Có thể bạn đọc sẽ thắc mắc: " Tại sao kiểu liệt kê Type ở trên không sử dụng generics? " Thực tế là trong Java việc sử dụng thuốc generic bị enumcấm. Vì vậy, ví dụ sau sẽ không biên dịch:
enum Type<T> {}

Học cao hơn

Để hiểu sâu hơn về cách hoạt động của bảng liệt kê trong Java, tôi khuyên bạn nên tự làm quen với mã nguồn của lớp java.lang.Enumvà cũng sử dụng trình dịch ngược Jad để nghiên cứu mã được tạo. Hơn nữa, việc nghiên cứu mã nguồn thư viện Java là hoàn toàn cần thiết để hiểu có bao nhiêu cơ chế trong Java hoạt động và rất hữu ích như một tài liệu tham khảo cho thiết kế hướng đối tượng. Link nguồn gốc: http://alexander.lds.lg.ua/
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION