enum-trong-java

Enum trong Java là một kiểu dữ liệu đặc biệt của Java được sử dụng để định nghĩa các tập hợp các hằng số. Cụ thể hơn, Java enum là một kiểu đặc biệt của lớp trong Java. Một enum có thể chứa các trường, phương thức và Constructor.

Nó có thể được sử dụng để định nghĩa các ngày trong tuần (SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY), các mùa trong năm (SPRING, SUMMER, FALL, WINTER), …

Java enum đã được thêm vào trong Java 5 cùng một số tính năng khác.

LUYỆN THI CHỨNG CHỈ OCA

Ví dụ Enum trong Java

Từ khóa Enum trong Java được sử dụng để tạo một kiểu enum. Hãy xem chương trình ví dụ java enum sau:

public enum ThreadStates {
	START,
	RUNNING,
	WAITING,
	DEAD;
}
Code language: PHP (php)

Trong ví dụ trên, ThreadStates là enum với các trường hằng số cố định START, RUNNING, WAITING và DEAD.

Java Enum vs Hằng số

Bây giờ chúng ta hãy xem enum tốt hơn các hằng số bình thường trong các lớp Java như thế nào.

Hãy tạo ra một class hằng số tương tự:

public class ThreadStatesConstant {
	public static final int START = 1;
	public static final int WAITING = 2;
	public static final int RUNNING = 3;
	public static final int DEAD = 4;
}Code language: PHP (php)

Bây giờ chúng ta hãy xem cách cả enum và hằng số được sử dụng trong một chương trình java:


/**
* This method shows the benefit of using Enum over Constants
*/
private static void benefitsOfEnumOverConstants() {
	//Enum values are fixed
	simpleEnumExample(ThreadStates.START);
	simpleEnumExample(ThreadStates.WAITING);
	simpleEnumExample(ThreadStates.RUNNING);
	simpleEnumExample(ThreadStates.DEAD);
	simpleEnumExample(null);
		
	simpleConstantsExample(1);
	simpleConstantsExample(2);
	simpleConstantsExample(3);
	simpleConstantsExample(4);
	//we can pass any int constant
	simpleConstantsExample(5);
}

private static void simpleEnumExample(ThreadStates th) {
	if(th == ThreadStates.START) System.out.println("Thread started");
	else if (th == ThreadStates.WAITING) System.out.println("Thread is waiting");
	else if (th == ThreadStates.RUNNING) System.out.println("Thread is running");
	else System.out.println("Thread is dead");
}
	
private static void simpleConstantsExample(int i) {
	if(i == ThreadStatesConstant.START) System.out.println("Thread started");
	else if (i == ThreadStatesConstant.WAITING) System.out.println("Thread is waiting");
	else if (i == ThreadStatesConstant.RUNNING) System.out.println("Thread is running");
	else System.out.println("Thread is dead");
}
Code language: PHP (php)

Nếu chúng ta nhìn vào ví dụ trên, chúng ta có hai rủi ro khi sử dụng các hằng số được enum giải quyết.

  1. Chúng ta có thể truyền bất kỳ hằng số int nào cho phương thức simpleConstantsExample() nhưng chúng ta chỉ có thể truyền các giá trị cố định cho simpleEnumExample, vì vậy nó cung cấp sự an toàn về kiểu.
  2. Chúng ta có thể thay đổi giá trị hằng số int trong class ThreadStatesConstant nhưng chương trình trên sẽ không ném ra bất kỳ ngoại lệ nào. Chương trình của tôi có thể không hoạt động như mong đợi nhưng nếu tôi thay đổi các hằng số enum, chúng tôi sẽ gặp lỗi thời gian biên dịch loại bỏ mọi khả năng xảy ra sự cố thời gian chạy.

Các phương thức Java Enum

Bây giờ chúng ta hãy xem thêm các tính năng của java enum với một ví dụ.


import java.io.Closeable;
import java.io.IOException;

/**
 * This Enum example shows all the things we can do with Enum types
 *
 */
public enum ThreadStatesEnum implements Closeable{
	START(1){
		@Override
		public String toString(){
			return "START implementation. Priority="+getPriority();
		}

		@Override
		public String getDetail() {
			return "START";
		}
	},
	RUNNING(2){
		@Override
		public String getDetail() {
			return "RUNNING";
		}
	},
	WAITING(3){
		@Override
		public String getDetail() {
			return "WAITING";
		}
	},
	DEAD(4){
		@Override
		public String getDetail() {
			return "DEAD";
		}
	};
	
	private int priority;
	
	public abstract String getDetail();
	//Enum constructors should always be private.
	private ThreadStatesEnum(int i){
		priority = i;
	}
	
	//Enum can have methods
	public int getPriority(){
		return this.priority;
	}
	
	public void setPriority(int p){
		this.priority = p;
	}
	
	//Enum can override functions
	@Override
	public String toString(){
		return "Default ThreadStatesConstructors implementation. Priority="+getPriority();
	}

	@Override
	public void close() throws IOException {
		System.out.println("Close of Enum");
	}
}
Code language: PHP (php)

Các điểm quan trọng của Java Enum

Dưới đây là một số điểm quan trọng đối với Enums trong Java.

  1. Tất cả java enum ngầm mở rộng java.lang.Enumlớp mà kéo dài lớp Object và dụng cụ Serializable và tương đương interface. Vì vậy, chúng tôi không thể mở rộng bất kỳ lớp nào trong enum.
  2. Vì enum là một từ khóa nên chúng ta không thể kết thúc tên gói với nó, ví dụ như com.journaldev.enumtên gói không hợp lệ.
  3. Enum có thể implement  . Như trong ví dụ trên enum, nó đang triển khai Closeablegiao diện.
  4. Các hàm tạo enum luôn ở chế độ riêng tư.
  5. Chúng ta không thể tạo phiên bản của enum bằng toán tử new.
  6. Chúng ta có thể khai báo các phương thức trừu tượng trong java enum, sau đó tất cả các trường enum phải triển khai phương thức trừu tượng. Trong ví dụ trên getDetail()là phương thức trừu tượng và tất cả các trường enum đã triển khai nó.
  7. Chúng ta có thể định nghĩa một phương thức trong enum và các trường enum cũng có thể ghi đè chúng. Ví dụ, toString()phương thức được định nghĩa trong enum và trường enum START đã ghi đè nó.
  8. Các trường enum trong Java có không gian tên, chúng ta chỉ có thể sử dụng trường enum với tên lớp như ThreadStates.START
  9. Enums có thể được sử dụng trong câu lệnh switch , chúng ta sẽ thấy nó hoạt động trong phần sau của hướng dẫn này.
  10. Chúng tôi có thể mở rộng enum hiện có mà không phá vỡ bất kỳ chức năng hiện có nào. Ví dụ: chúng ta có thể thêm một trường mới MỚI trong enum ThreadStates mà không ảnh hưởng đến bất kỳ chức năng hiện có nào.
  11. Vì các trường enum là hằng số, phương pháp hay nhất trong java là viết chúng bằng các chữ cái khối và gạch dưới cho khoảng trắng. Ví dụ EAST, WEST, EAST_DIRECTION, v.v.
  12. Các hằng số enum hoàn toàn là tĩnh và là cuối cùng
  13. Hằng số enum là cuối cùng nhưng biến của nó vẫn có thể được thay đổi. Ví dụ, chúng ta có thể sử dụng setPriority()phương thức để thay đổi mức độ ưu tiên của hằng số enum. Chúng ta sẽ thấy nó được sử dụng trong ví dụ dưới đây.
  14. Vì các hằng số enum là cuối cùng, chúng ta có thể so sánh chúng một cách an toàn bằng cách sử dụng các phương thức “==” và equals (). Cả hai sẽ có cùng một kết quả.

Java EnumSet, EnumMap, valueOf ()

Bây giờ chúng ta đã biết hầu hết các tính năng của Enum, chúng ta hãy xem chương trình ví dụ Java Enum. Sau đó, chúng ta sẽ tìm hiểu thêm một số tính năng của enum.


package com.journaldev.enums;

import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;

public class JavaEnumExamples {

	public static void main(String[] args) throws IOException {
				
		usingEnumMethods();
		
		usingEnumValueOf();
		
		usingEnumValues();
		
		usingEnumInSwitch(ThreadStatesEnum.START);
		usingEnumInSwitch(ThreadStatesEnum.DEAD);
		
		usingEnumMap();
		
		usingEnumSet();
		
	}

	private static void usingEnumSet() {
		EnumSet enumSet = EnumSet.allOf(ThreadStatesEnum.class);
		for(ThreadStatesEnum tsenum : enumSet){
			System.out.println("Using EnumSet, priority = "+tsenum.getPriority());
		}
	}

	private static void usingEnumMap() {
		EnumMap<ThreadStatesEnum, String> enumMap = new EnumMap<ThreadStatesEnum,String>(ThreadStatesEnum.class);
		enumMap.put(ThreadStatesEnum.START, "Thread is started");
		enumMap.put(ThreadStatesEnum.RUNNING, "Thread is running");
		enumMap.put(ThreadStatesEnum.WAITING, "Thread is waiting");
		enumMap.put(ThreadStatesEnum.DEAD, "Thread is dead");
		
		Set keySet = enumMap.keySet();
		for(ThreadStatesEnum key : keySet){
			System.out.println("key="+key.toString()+":: value="+enumMap.get(key));
		}
		
	}

	private static void usingEnumInSwitch(ThreadStatesEnum th) {
		switch (th){
		case START:
			System.out.println("START thread");
			break;
		case WAITING:
			System.out.println("WAITING thread");
			break;
		case RUNNING:
			System.out.println("RUNNING thread");
			break;
		case DEAD:
			System.out.println("DEAD thread");
		}
	}

	private static void usingEnumValues() {
		ThreadStatesEnum[] thArray = ThreadStatesEnum.values();
		
		for(ThreadStatesEnum th : thArray){
			System.out.println(th.toString() + "::priority="+th.getPriority());
		}
	}

	private static void usingEnumValueOf() {
		ThreadStatesEnum th = Enum.valueOf(ThreadStatesEnum.class, "START");
		System.out.println("th priority="+th.getPriority());
	}

	private static void usingEnumMethods() throws IOException {
		ThreadStatesEnum thc = ThreadStatesEnum.DEAD;
		System.out.println("priority is:"+thc.getPriority());
		
		thc = ThreadStatesEnum.DEAD;
		System.out.println("Using overriden method."+thc.toString());
		
		thc = ThreadStatesEnum.START;
		System.out.println("Using overriden method."+thc.toString());
		thc.setPriority(10);
		System.out.println("Enum Constant variable changed priority value="+thc.getPriority());
		thc.close();
	}

}
Code language: JavaScript (javascript)

Trước khi giải thích các tính năng quan trọng khác của enum, chúng ta hãy xem đầu ra của chương trình trên.


priority is:4
Using overriden method.Default ThreadStatesConstructors implementation. Priority=4
Using overriden method.START implementation. Priority=1
Enum Constant variable changed priority value=10
Close of Enum
th priority=10
START implementation. Priority=10::priority=10
Default ThreadStatesConstructors implementation. Priority=2::priority=2
Default ThreadStatesConstructors implementation. Priority=3::priority=3
Default ThreadStatesConstructors implementation. Priority=4::priority=4
START thread
DEAD thread
key=START:: value=Thread is started
key=RUNNING:: value=Thread is running
key=WAITING:: value=Thread is waiting
key=DEAD:: value=Thread is dead
Using EnumSet, priority = 10
Using EnumSet, priority = 2
Using EnumSet, priority = 3
Using EnumSet, priority = 4
Code language: PHP (php)

Điểm quan trọng

  1. Các phương thức usingEnumMethods() chỉ ra cách tạo một đối tượng enum và cách chúng ta có thể sử dụng các phương thức của nó. Nó cũng cho thấy việc sử dụng phương thức setPriorty(int i) để thay đổi biến của enum.
  2. usingEnummValueOf() cho thấy cách sử dụng java.util.EnumValueOf(enumType, name) mà qua đó chúng ta có thể tạo một đối tượng enum từ String. Nó ném IllegalArgumentException nếu kiểu enum được chỉ định không có hằng số với tên được chỉ định hoặc đối tượng lớp được chỉ định không đại diện cho kiểu enum. Nó cũng ném NullPointerException nếu bất kỳ đối số nào là rỗng.
  3. Phương thức usingEnumValues() hiển thị cách sử dụng phương thức giá trị () trả về một mảng chứa tất cả các giá trị của enum theo thứ tự chúng được khai báo. Lưu ý rằng phương thức này được tạo tự động bởi trình biên dịch java cho mọi enum. Bạn sẽ không tìm thấy việc triển khai giá trị () trong lớp java.util.Enum.
  4. Các usingEnumInSwitch() chương trình phương pháp làm thế nào để sử dụng hằng enum trong trường hợp chuyển đổi.
  5. Phương pháp usingEnumMap() cho thấy việc sử dụng java.util.EnumMap, được giới thiệu trong Java 1.5 Collections Framework. EnumMap là triển khai Bản đồ để sử dụng với các khóa kiểu enum. Tất cả các khóa trong bản đồ enum phải đến từ một kiểu enum duy nhất được chỉ định, rõ ràng hoặc ngầm định, khi bản đồ được tạo. Chúng tôi không thể sử dụng null làm khóa cho EnumMap và EnumMap không được đồng bộ hóa.
  6. Phương thức usingEnumSet() hiển thị việc sử dụng java.util.EnumSet , là thiết lập triển khai để sử dụng với các kiểu enum. Tất cả các phần tử trong một tập hợp enum phải đến từ một kiểu enum duy nhất được chỉ định, rõ ràng hoặc ngầm định, khi tập hợp được tạo. EnumSet không được đồng bộ hóa và các phần tử rỗng không được phép. Nó cũng cung cấp một số phương pháp hữu ích như copyOf(Collection c), of(E first, E… rest)và complementOf(EnumSet s). 

Trên đây là kiến thức về Enum và ví dụ Enum trong Java.

Happy learning!!!

Bài viết liên quan

Leave a Reply

Your email address will not be published.