1. Bối cảnh hình enumthành

Hôm nay chúng ta sẽ khám phá một loại kiểu dữ liệu khác trong Java: enum. Tên enumxuất phát từ liệt kê từ . Loại dữ liệu này là gì và nó dùng để làm gì?

Đôi khi một lập trình viên cần tạo một kiểu dữ liệu mới, mà các giá trị có thể có của nó được giới hạn trong một danh sách cố định nhỏ.

Ví dụ: một DayOfTheWeekloại chỉ có thể nhận các giá trị MONDAY, TUESDAY, WEDNESDAY, ... Tổng cộng có 7 giá trị. Hoặc một Monthloại chỉ có thể nhận các giá trị JANUARY, FEBRUARY, MARCH, ... Tổng cộng có 12 giá trị.

Tất nhiên, bạn sử dụng các số có thể ( intloại): 1— Thứ Hai, 2— Thứ Ba, v.v. Nhưng ai đó có thể vô tình gán các giá trị không hợp lệ như 8hoặc 0cho biến của bạn.

Bạn có thể dễ dàng gặp tình huống trong đó một lập trình viên nghĩ rằng các ngày trong tuần (hoặc các tháng trong năm) được đánh số bắt đầu từ 0, trong khi những người khác lại mong đợi việc đánh số của họ bắt đầu từ một, v.v.

Đó là lý do tại sao Java đã giới thiệu enum, một kiểu dữ liệu bao gồm một tập hợp hữu hạn các giá trị .


2. Khai báo kiểu

Khai báo một kiểu dữ liệu mới enumtrông như thế này:

enum TypeName
{
   VALUE1,
   VALUE2,
   VALUE3
}

Đâu TypeNamelà tên của loại (lớp) mới và các giá trị có thể được phân tách bằng dấu phẩy và được bao trong dấu ngoặc nhọn: Value1, Value2, Value3.

Ví dụ: hãy tạo của riêng chúng tôi DayOfTheWeek enum:

Mã số Ghi chú
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY
}
DayLoại mới

Thứ hai
Thứ ba Thứ
tư Thứ
năm Thứ sáu
Thứ bảy
Chủ
nhật

Đây là cách bạn gán một giá trị cho một biến kiểu mới của chúng ta:

Day day = Day.MONDAY;

Ví dụ:

Mã số Ghi chú
Day day = Day.FRIDAY;
System.out.println(day);
Đầu ra màn hình sẽ là:
FRIDAY


3. Phương pháp của mộtenum

Một enumloại có một số phương thức tích hợp sẵn, hai trong số đó rất thú vị:

Phương thức tĩnh values()trả về một mảng gồm tất cả các giá trị của enumkiểu:

Mã số Ghi chú
Day[] days = Day.values();

for (Day day: days)
   System.out.println(day);







System.out.println(days[2]);
Biến dayslưu một mảng chứa các giá trị của Daykiểu dữ liệu (7 phần tử)

Hiển thị nội dung của mảng ra màn hình:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY

WEDNESDAY

Phương ordinal()thức trả về số thứ tự của hằng số. Bạn gọi nó trên một enumgiá trị chứ không phải là một enumlớp:

Mã số Đầu ra bảng điều khiển
System.out.println(Day.MONDAY.ordinal());
System.out.println(Day.FRIDAY.ordinal());
System.out.println(Day.SUNDAY.ordinal());
0
4
6


4. Chuyển đổi thành một lớp

Trong thực tế, không có gì kỳ diệu ở đây. Trình biên dịch vừa cung cấp cho chúng tôi một số đường cú pháp. Tại thời điểm biên dịch, Dayenum được chuyển đổi thành một lớp thông thường:

Mã, phiên bản đơn giản hóa Ghi chú
public class Day
{
   public static final Day MONDAY = new Day(0);
   public static final Day TUESDAY = new Day(1);
   public static final Day WEDNESDAY = new Day(2);
   public static final Day THURSDAY = new Day(3);
   public static final Day FRIDAY = new Day(4);
   public static final Day SATURDAY = new Day(5);
   public static final Day SUNDAY = new Day(6);

    private static final Day[] array = {MONDAY, TUESDAY,
      WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};

   private final int value;

   private Day (int value)
   {
      this.value = value;
   }

   public int ordinal()
   {
      return this.value;
   }

   public static Day[] values()
   {
      return array;
   }
}
Daylớp

Danh sách các hằng số tĩnh







Một mảng chứa tất cả các giá trị của Dayenum


Một biến lưu trữ giá trị của một Dayđối tượng cụ thể

Lớp là riêng tư, có nghĩa là các đối tượng của Daylớp chỉ có thể được tạo bên trong lớp. Phương thức phải được gọi trên một đối tượng. Nó trả về giá trị của đối tượng — trường. Phương thức trả về một mảng tĩnh với tất cả các giá trị của lớpconstructorDayDay



ordinalDay

value


Day

Nếu chúng ta loại bỏ tất cả các phương thức và biến tĩnh khỏi Daylớp, chúng ta sẽ nhận được như sau:

Mã số Ghi chú
public class Day
{
  private int value;

  private Day (int value)
  {
    this.value = value;
  }

  public int ordinal()
  {
    return this.value;
  }
}


Biến valuelưu trữ giá trị của Dayđối

Daytượng Các đối tượng chỉ có thể được tạo bên trong Daylớp, vì hàm tạo là private.




Phương ordinal()thức trả về valueđối Daytượng.

Nói cách khác, không có gì đáng sợ đang xảy ra ở đây. Trình biên dịch tạo Daylớp, thêm các hằng số đại diện cho enumcác giá trị, thêm các phương thức cần thiết và tạo hàm tạo của lớp private. Chúng ta sẽ xem xét cách các hàm tạo hoạt động sau.

Hy vọng rằng bây giờ đã rõ tại sao chúng ta gán giá trị cho một biến theo cách này:

Day day = Day.MONDAY;

MONDAYchỉ là một trường tĩnh (hằng số) trong Daylớp. Khi truy cập các phương thức và trường tĩnh từ bên ngoài lớp, bạn phải chỉ ra tên lớp trước tên của trường hoặc phương thức.



5. Nhiều phương pháp của mộtenum

Mỗi enumlớp có một số tính năng thú vị.

Chuyển đổi sang và từ một chuỗi

Để chuyển đổi một đối tượng enum thành một chuỗi, bạn cần gọi toString()phương thức của nó.

String str = Day.MONDAY.toString();

Để chuyển đổi theo hướng khác (từ chuỗi thành Dayđối tượng), bạn có thể sử dụng valueOf()phương thức tĩnh:

Day day = Day.valueOf("MONDAY");

Nó siêu tiện lợi và sẽ hữu ích trong nhiều trường hợp.

Chuyển đổi thành một số và ngược lại

Bạn đã biết cách chuyển đổi một enumđối tượng thành một số: gọi ordinal()phương thức:

int index = Day.MONDAY.ordinal();

Để chuyển đổi theo hướng khác (từ một số sang một Dayđối tượng), bạn cần một cấu trúc rõ ràng hơn:

Day day = Day.values()[2];

Ví dụ:

Mã số Ghi chú
Day day = Day.MONDAY;
int index = day.ordinal();
Day newDay = Day.values()[index+2];
Thứ Hai
Lấy chỉ số của Thứ Hai: 0
Ngày trong tuần 2 ngày sau Thứ Hai

Điểm quan trọng:enumcác giá trị là một tập hợp các hằng số cố định nên chúng có thể được so sánh bằng cách sử dụng == . Nói cách khác, bạn không thể có hai MONDAYđối tượng giống hệt nhau với địa chỉ khác nhau. Chỉ tồn tại một phiên bản duy nhất của mỗi giá trị enum. Và điều đó có nghĩa là việc so sánh các biến enum bằng == sẽ luôn hoạt động.



6. Thêm các phương thức của riêng bạn vào mộtenum

Bởi vì an enumbiến thành một lớp bình thường khi biên dịch, bạn có thể khai báo các phương thức trong đó. Các phương thức này chỉ đơn giản là được thêm vào lớp mà trình biên dịch tạo ra. Ví dụ: giả sử chúng tôi muốn Day enumtrả về một danh sách các giá trị enum thay vì một mảng.

Sau đó, chúng ta có thể thêm đoạn mã sau:

Mã số Ghi chú
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY;

   public static List<Day> asList()
   {
      ArrayList<Day> list = new ArrayList<Day>();

      Collections.addAll(list, values());

      return list;
   }

}








Dấu chấm phẩy là bắt buộc sau danh sách các giá trị.



Tạo một ArrayListđối tượng

Thêm các giá trị trong mảng mà values()phương thức trả về.
Trả lại danh sách.

Bây giờ phương thức này có thể được gọi bằng mã:

Mã số Ghi chú
List<Day> list = Day.asList();
Biến listsẽ lưu trữ một danh sách tất cả các giá trị của Day enum.