Класс перечисления Java для продвинутого изучения

Java

Тип перечисления является частью новых функций в Java 5. Это особый тип данных. Причина особенная, потому что он одновременно является типом класса и имеет более специальные ограничения, чем типы классов, но эти ограничения Существование типа перечисления также создает простота, безопасность и удобство.

△Некоторые места до конца не изучены, и я продолжу изучать и дорабатывать эту статью позже.

1. Обучение класса перечисления

1.1 Определение класса перечисления

  • Класс перечисления может реализовывать один или несколько интерфейсов.Класс перечисления, определенный enum, по умолчанию наследует класс java.lang.Enum, а не класс Object по умолчанию, поэтому класс перечисления не может явно наследовать другие родительские классы. Класс java.lang.Enum реализует два интерфейса: java.lang.Serializable и java.lang.Comparable. Неабстрактные классы перечисления, определенные с помощью enum, будут завершены по умолчанию, поэтому классы перечисления не могут быть производными от подклассов.
  • Конструктор класса перечисления может использовать только частный контроллер доступа.Если контроллер доступа конструктора опущен, по умолчанию используется частный модификатор, если контроллер доступа является обязательным, может быть указан только частный модификатор.
  • Все экземпляры класса перечисления должны быть явно перечислены в первой строке класса перечисления, иначе класс перечисления никогда не создаст экземпляр. При перечислении этих экземпляров система автоматически добавит публичное статическое окончательное оформление без необходимости их явного добавления программистами.
  • Класс перечисления по умолчанию предоставляет метод values(), который может легко проходить все значения перечисления.

Определим константы с понедельника по воскресенье следующим образом.

//Day.class
//枚举类型,使用关键字enum
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Короче говоря, ключевое слово, которое мы используем при определении типа перечисления, — это enum, которое похоже на ключевое слово class, за исключением того, что первое определяет тип перечисления, а второе определяет тип класса.

1.2 Принцип реализации класса перечисления

После того, как мы получили общее представление об определении и простом использовании типов перечисления, теперь необходимо понять основные принципы реализации типов перечисления. на самом деле используя ключевое словоenumПосле создания типа перечисления и компиляции компилятор сгенерирует для нас родственный класс, этот класс наследуетJava APIсерединаjava.lang.Enumclass, то есть через ключевое словоenumСоздание типа перечисления на самом деле является типом класса после компиляции, и класс наследуется отjava.lang.Enumсвоего рода.

Посмотрите декомпилированный файл Day.class:

//反编译Day.class
final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}
  • ①Из декомпилированного кода видно, что компилятор помог нам сгенерировать класс Day (обратите внимание, что это класс final и не будет унаследован), и этот класс наследуется отjava.lang.Enumclass, который является абстрактным классом (позже мы разберем основные методы этого класса).
  • ② Кроме того, компилятор также помог нам сгенерировать 7 экземпляров объектов типа Day, соответствующих 7 датам, определенным в перечислении, что полностью объясняет, что каждый из типов Day, которые мы определили ранее с помощью ключевого слова enum. Константа перечисления даты также является реальный объект экземпляра Day, но содержимое отличается. Обратите внимание, что компилятор также генерирует для нас два статических метода, а именноvalues()和 valueOf().
  • ③На данный момент мы также понимаем, что тип перечисления, определенный с помощью ключевого слова enum, также будет преобразован в реальный класс после периода компиляции, и в этом классе будет каждый тип перечисления в типе перечисления.Определите соответствующий объект экземпляра переменной, как указано вышеMONDAYСоответствие типам перечисленияpublic static final Day MONDAY;, и компилятор создаст для класса два метода:values()和valueOf(). На данный момент я считаю, что наш принцип реализации перечисления относительно ясен. Давайте более подробно рассмотрим класс java.lang.Enum и назначение функций values() и valueOf().

1.3 Общие методы подсчета

2. Использование классов перечисления

2.1 Константы

Существует три способа реализации констант в системе: константы интерфейса, константы класса и константы перечисления.

2.1.1 Константы интерфейса

Например, в качели java есть SwingConstant:

public interface SwingConstants {

        /** 
         * The central position in an area. Used for
         * both compass-direction constants (NORTH, etc.)
         * and box-orientation constants (TOP, etc.).
         */
        public static final int CENTER  = 0;

        // 
        // Box-orientation constant used to specify locations in a box.
        //
        /** 
         * Box-orientation constant used to specify the top of a box.
         */
        public static final int TOP     = 1;
        /** 
         * Box-orientation constant used to specify the left side of a box.
         */
        public static final int LEFT    = 2;
       
       //。。。省略其他代码
   }

2.1.2 Константы класса

Метод написания (1) Плюсы и минусы: При использовании значения DefaultValues.DEFAULT_AP вы должны прочитать аннотации в классе, чтобы знать, что он представляет собой центр. Если констант много, то ставить все константы в этот интерфейс не очень дружелюбно.

/**
 * 系统默认值
 *
 */
public class DefaultValues {

	/**
	 * 默认密码
	 */
	public static final String DEFAULT_PASSWORD = "000000";
	/**
	 * 默认用户类型
	 */
	public static final String DEFAULT_USER_TYPE = UserType.NormalUser.value();	
	/**
	 * 默认获取api名称
	 */
	public static final String DEFAULT_API = "api";
	
	/**
	 * 默认系统字符编码
	 */
	public static final String DEFAULT_ENCODING = "UTF-8";
	
	/**集群规模*/
	public static final  long CLUSTER_SIZE = 1000;
}

Метод написания (2) Плюсы и минусы: Константы интерфейса компании представляют собой статические внутренние классы, определенные в интерфейсе, которые могут дополнительно классифицировать константные классы различных функций. Константы разных функций помещаются во внутренний класс интерфейса, и значение константы может быть ясно известно через разные внутренние классы.

public class Constants {
	public static class MimeType{
		public static final String BIN = "application/octet-stream";
		public static final String CSS = "text/css";
		public static final String DOC = "application/msword";
		public static final String DOCX = "";
		public static final String EXE = "application/octet-stream";
		public static final String GTAR = "application/x-gtar";
		public static final String GZ = "application/x-gzip";
		public static final String HTM = "text/html;charset=utf-8";
		public static final String ICO = "image/x-icon";
		public static final String JPEG = "image/jpeg";
		public static final String JPG = "image/jpeg";
		public static final String JS = "application/x-javascript;charset=utf-8";
		public static final String JSON = "application/json;charset=utf-8";
		public static final String FORM = "application/x-www-form-urlencoded; charset=UTF-8";
		public static final String MULTIPART = "multipart/form-data; charset=UTF-8";
		public static final String MHT = "message/rfc822";
		public static final String MHTML = "message/rfc822";
		public static final String MOV = "video/quicktime";
		public static final String MP3 = "audio/mpeg";
		public static final String MPE = "video/mpeg";
		public static final String MPEG = "video/mpeg";
		public static final String MPG = "video/mpeg";
		public static final String PDF = "application/pdf";
		public static final String PPT = "application/vnd.ms-powerpoint";
		public static final String RTF = "application/rtf";
		public static final String SWF = "application/x-shockwave-flash";
		public static final String TAR = "application/x-tar";
		public static final String TXT = "text/plain;charset=utf-8";
		public static final String WAV = "audio/x-wav";
		public static final String XML = "text/xml;charset=utf-8";
		public static final String ZIP = "application/zip";
		
	}
	
	public static class DataState{
		public static final String FLAG_REMOVE = "Y";
		public static final String FLAG_NORMAL = "N";
	}
	
	/**
	 * 应用服务器实例运行状态
	 */
	public static class ServerASInstanceState{
		public static final int RUNNING = 1;
		public static final int SHUT_OFF = 2;
	}
	/**
	 * WebServices接口分析
	 */
	public static class WebServicesType{
		/**先接收数据,在返回接口情况的接口 **/ 
		public static final String IN_OUT = "IO";
		/**先发数据请求,后返回数据的接口 **/ 
		public static final String OUT_IN = "OI";
		/**只发送数据的接口**/ 
		public static final String OUT= "O";
		/**只接收数据的接口 **/ 
		public static final String IN = "I";
	}
	
	/**
	 * 任务调度使用
	 */
	public static class TaskScheduling{
		/**任务ID **/ 
		public static final String TASK_ID = "taskID";
		/**任务URL **/ 
		public static final String TASK_URI = "taskURI";
		/**任务URL **/ 
		public static final String TASK_NAME = "taskName";
		/**任务目标服务器IP **/ 
		public static final String TASK_SERVER_IP = "taskServerIp";
		/**任务目标服务器IP **/ 
		public static final String TASK_SERVER_PORT = "taskServerPort";
		
		/**任务状态启用**/
		public static final int TASK_ENABLED = 1;
		
		/**任务状态禁用**/
		public static final int TASK_DISABLE = 0;
		
		/**每年任务**/
		public static final int TYPE_EVERY_YEAR= 1;
		
		/**每月任务**/
		public static final int TYPE_EVERY_MONTH = 2;
		
		/**每日任务**/
		public static final int TYPE_EVERY_DAY = 3;
		
		/**每周任务**/
		public static final int TYPE_EVERY_WEEK = 4;
		
		/**单次任务**/
		public static final int TYPE_SINGLE = 5;
		
	}
}

Хотя есть перечисление, это может быть связано с привычкой дизайнера, и есть много констант классов, используемых людьми.Map<Integer, String>Чтобы инкапсулировать информацию, соответствующую константе, вstaticВ блоке кода put выполняется при инициализации класса. когда используешьResponseCode.RESP_INFO.get("DATABASE_EXCEPTION");Информацию об ответе можно вынести.Так как проект отделен от фронта и бэкенда, код состояния нужно прописать в интерфейсном документе, а также прописать подсказку, соответствующую коду состояния.Кроме того, наш ответ Класс RespInfo имеет атрибут сообщения, который заключается в сохранении кода состояния в константе класса соответствующей информации.

public class ResponseCode {

    /** 系统处理正常 */
    public static final int SUCCESS_HEAD = 0;

    /** 系统处理未知异常 */
    public static final int EXCEPTION_HEAD = 1;

    /** JSON解析错误 */
    public static final int JSON_RESOLVE = 2;

    /** 类型不匹配 */
    public static final int TRANSTYPE_NO = 3;

    /** Head - messageID未赋值 */
    public static final int HEAD_messageID = 4;

    /** Head - timeStamp未赋值 */
    public static final int HEAD_timeStamp = 5;

    /** Head - messengerID未赋值 */
    public static final int HEAD_messengerID = 6;

    /** Head - transactionType 未赋值 */
    public static final int HEAD_transactionType = 7;

    /** digest校验不通过 */
    public static final int HEAD_DIGEST = 8;
    
    /** src校验不通过 */
    public static final int HEAD_SRC_NULL = 10;
    
    /** 协议包含非法字符 */
    public static final int ILLEGAL_MESSAGE = 11;

    /** 数据库异常 */
    public static final int DATABASE_EXCEPTION = 9;
    public static final Map<Integer, String> RESP_INFO = new HashMap<Integer, String>();

    static {
        // Head 相关
        RESP_INFO.put(SUCCESS_HEAD, "系统处理正常");
        RESP_INFO.put(EXCEPTION_HEAD, "系统处理未知异常");
        RESP_INFO.put(JSON_RESOLVE, "JSON解析错误");
        RESP_INFO.put(TRANSTYPE_NO, "类型不匹配");
        RESP_INFO.put(HEAD_messageID, "messageID未赋值");
        RESP_INFO.put(HEAD_timeStamp, "timeStamp未赋值");
        RESP_INFO.put(HEAD_messengerID, "messengerID未赋值");
        RESP_INFO.put(HEAD_transactionType, "transactionType未赋值");
        RESP_INFO.put(HEAD_DIGEST, "digest校验不通过");
        RESP_INFO.put(DATABASE_EXCEPTION, "数据库异常");
        RESP_INFO.put(HEAD_SRC_NULL, "src未赋值");
        RESP_INFO.put(ILLEGAL_MESSAGE, "协议包含非法字符");
        
    }
}

2.1.3 Константы перечисления

Все классы перечисления являются подклассами класса Enum, как и класс Object, но они не написаны, поэтому классы перечисления могут вызывать методы Enum. Обратите внимание, что атрибуты разделяются запятыми.Только если после атрибута нет метода, вы можете добавить точку с запятой или нет в конце.

Письмо (1)

public enum StateType {
	/**
	 * 成功返回状态
	 */
	OK(200,"OK"), 
	
	/**
	 * 请求格式错误
	 */
	BAD_REQUEST(400,"bad request"),
	/**
	 * 未授权
	 */
	UNAUTHORIZED(401,"unauthorized"),
	/**
	 * 没有权限
	 */
	FORBIDDEN(403,"forbidden"),
	
	/**
	 * 请求的资源不存在
	 */
	NOT_FOUND(404,"not found"),
	/**
	 * 该http方法不被允许
	 */
	NOT_ALLOWED(405,"method not allowed"),
	/**
	 * 请求处理发送异常
	 */
	PROCESSING_EXCEPTION(406,"Handling Exceptions"),
	/**
	 * 
	 * 请求处理未完成
	 */
	PROCESSING_UNFINISHED(407,"To deal with unfinished"),
	
	/**
	 * 登录过期
	 */
	BEOVERDUE(408,"Be overdue"),
	
	/**
	 * 用户未登录
	 */
	NOT_LOGIN(409,"Not logged in"),
	
	/**
	 * 这个url对应的资源现在不可用
	 */
	GONE(410,"gone"),
	/**
	 * 请求类型错误
	 */
	UNSUPPORTED_MEDIA_TYPE(415,"unsupported media type"),
	/**
	 * 校验错误时用
	 */
	UNPROCESSABLE_ENTITY(422,"unprocessable entity"),
	/**
	 * 请求过多
	 */
	TOO_MANY_REQUEST(429,"too many request");

	private int code;
	private String value = null;

	private StateType(int code,String value) {
		this.code = code;
		this.value = value;
	}

	public String value() {
		return this.value;
	}

	public int getCode() {
		return code;
	}

	public static Boolean isValidateStateType(String... stateType) {
		for (int i = 0; i < stateType.length; i++) {
			StateType [] value = StateType.values();
			boolean falg = false;
			for(StateType type : value) {
				if(type.value.equals(stateType[i])) {
					falg = true;
				}
				
			}
			if(!falg) {
				return falg;
			}
		}
		return true;
	}
}

/*使用*/
public static void main(String[] args) {
	System.out.println("状态码:"+StateType.getCode());
        System.out.println("错误信息:"+StateType.getValue());
}

Письмо (2)

public enum Level {
	/**
	 * 第一层
	 */
	One(1),
	/**
	 * 第二层 
	 */
	Two(2),
	/**
	 * 第三层
	 */
	Three(3),
	/**
	 * 第四层
	 */
	Four(4),
	/**
	 * 第五层
	 */
	Five(5);
	
	private int value;
	
	Level(int value) {
		this.value = value;
	}
	
	public int value() {
		return this.value;
	}
	
	public static Boolean isValidateLevel(int level) {
		Level [] value = Level.values();
		boolean falg = false;
		for (Level pl : value){
			if(pl.value == level){
				falg = true;
			}
		}
		return falg;
	}
}

/*使用*/
public static void main(String[] args) {
	System.out.println("楼层:"+Level.Three);
}

2.2 переключатель в сочетании с классом перечисления

Оператор switch до JDK1.6 поддерживает только типы int, char и enum.Использование перечисления может сделать наш код более читабельным.

Перечисление — это объявление набора именованных констант.Когда переменная имеет несколько возможных значений, ее можно определить как тип перечисления. Перечисление заключается в перечислении значений переменных одно за другим, а значения переменных ограничены диапазоном перечисленных значений.

△ Примечание:Перечисления — это просто типы перечислений, и им нельзя присваивать назначения. следующее:GREEN默认值为0,ноGREEN不能=0, потому что типы данных разные. Переменные в перечислении не назначаются напрямую, значение по умолчанию равно предыдущему значению переменной плюс один, а значение по умолчанию равно 0.

enum Signal { 
 GREEN, YELLOW, RED 
} 
public class TrafficLight { 
 Signal color = Signal.RED; 
 public void change() { 
  switch (color) { 
  case RED: 
   color = Signal.GREEN; 
   break; 
  case YELLOW: 
   color = Signal.RED; 
   break; 
  case GREEN: 
   color = Signal.YELLOW; 
   break; 
  } 
 } 
} 

2.3 Добавление новых методов в перечисление

Если вы планируете настроить свои собственные методы, вы должны добавить точку с запятой (";") в конце последовательности экземпляров enum.В java вы должны сначала определить экземпляр java.

public enum ChannelEnum {

    MSG_CENTER_CHANNEL1("msg_center_channel1"),
    MSG_CENTER_CHANNEL("msg_center_channel");

    private String channel = null;

    private ChannelEnum(String channel) {
        this.channel = channel;
    }

    public String getChannel() {
        return this.channel;
    }
}

2.4 Реализация интерфейса

  • Все перечисления наследуются от класса java.lang.Enum. Поскольку Java не поддерживает множественное наследование, объекты перечисления больше не могут наследоваться от других классов.
  • Если метод в интерфейсе реализован классом перечисления, каждое значение перечисления будет вести себя одинаково при вызове метода (поскольку тело метода точно такое же). Если вам нужно, чтобы каждое значение перечисления вело себя по-разному при вызове метода, вы можете сделать так, чтобы каждое значение перечисления реализовывало метод отдельно, каждое значение перечисления предоставляло другую реализацию, чтобы разные значения перечисления Values ​​вели себя по-разному при вызове этого метода.
public interface Behaviour {  
    void print();  
    String getInfo();  
}  
public enum Color implements Behaviour{  
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);  
    // 成员变量  
    private String name;  
    private int index;  
    // 构造方法  
    private Color(String name, int index) {  
        this.name = name;  
        this.index = index;  
    }  
//接口方法  
    @Override  
    public String getInfo() {  
        return this.name;  
    }  
    //接口方法  
    @Override  
    public void print() {  
        System.out.println(this.index+":"+this.name);  
    }  
}

2.5 Организация перечислений с интерфейсами

public interface Food {
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}

Оригинальный адрес данных: