Java枚举深入理解以及HttpStatus类的使用
1枚举
1.1枚举基础
由于每个程序员在开始编程时一般会首先学习C/C++,然后再学习Java,在C++中枚举是可以定义枚举值为特定的整数的,但这在Java中却没有得到支持,大概C/C++中的枚举代表了数值型常量多一些,而Java中枚举值,更确切的说为枚举类型对象。在Java中定义一个简单的枚举类如下所示:
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
枚举类与switch-case语句有着天然的结合使用的特性,如对上述的Season类型,编写一个简单的HTTP get接口
代码如下:
@RequestMapping("/testSeason")
public String testSeason() {
Season season = SPRING;
switch (season) {
case AUTUMN:
System.out.println(season.toString());
break;
case SPRING:
System.out.println(season.toString());
break;
case SUMMER:
System.out.println(season.toString());
break;
case WINTER:
System.out.println("秋天到了");
break;
default:
System.out.println("impossible");
break;
}
return season.toString();//SPRING
}
1.2高级枚举
在Java中枚举类会默认继承类java.lang.Enum,
通过IDEA生成Season的继承层次结构图如下:
关于枚举的常见用法可以参见下图:
1.2.1 values和 valueOf(String name)
代码演示上述图片中的前两项
Season[] seasons = Season.values();
for (int i = 0; i < seasons.length; i++) {
System.out.println(seasons[i]);
}
/*
SPRING
SUMMER
AUTUMN
WINTER
*/
Season season1 = Season.valueOf("SPRING");
System.out.println(season1);
/*
SPRING
*/
System.out.println(season.equals(season1));
/*
true
*/
对应的输出已经打印在显示在代码中,方便理解。
至于高级特性中的多态暂时不在此阐述,编程过程中,不常用。
2 HttpStatus
HttpStatus为建模HTTP的响应码,对于一个HTTP请求,为了表示该次请求在服务器处理时展示的各种情况而建模的,如常见的302表示重定向,而200错误码则表示请求被正确的处理。
之前自己一直不知道该如何为枚举设置特定的值,因为有很多情况比如说出差时开发的访客状态,7表示访客的状态为6、7、8、9,并不是从0开始编写的,当时就写的比较笨,单独去判断是不是等于6,而没有使用HttpStatus类的这种用法。
public enum HttpStatus {
CONTINUE(100, "Continue"),
SWITCHING_PROTOCOLS(101, "Switching Protocols"),
PROCESSING(102, "Processing"),
CHECKPOINT(103, "Checkpoint"),
OK(200, "OK"),
CREATED(201, "Created"),
ACCEPTED(202, "Accepted"),
NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
NO_CONTENT(204, "No Content"),
RESET_CONTENT(205, "Reset Content"),
PARTIAL_CONTENT(206, "Partial Content"),
MULTI_STATUS(207, "Multi-Status"),
ALREADY_REPORTED(208, "Already Reported"),
IM_USED(226, "IM Used"),
MULTIPLE_CHOICES(300, "Multiple Choices"),
MOVED_PERMANENTLY(301, "Moved Permanently"),
FOUND(302, "Found"),
/** @deprecated */
@Deprecated
MOVED_TEMPORARILY(302, "Moved Temporarily"),
SEE_OTHER(303, "See Other"),
NOT_MODIFIED(304, "Not Modified"),
/** @deprecated */
@Deprecated
USE_PROXY(305, "Use Proxy"),
TEMPORARY_REDIRECT(307, "Temporary Redirect"),
PERMANENT_REDIRECT(308, "Permanent Redirect"),
BAD_REQUEST(400, "Bad Request"),
UNAUTHORIZED(401, "Unauthorized"),
PAYMENT_REQUIRED(402, "Payment Required"),
FORBIDDEN(403, "Forbidden"),
NOT_FOUND(404, "Not Found"),
METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
NOT_ACCEPTABLE(406, "Not Acceptable"),
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"),
REQUEST_TIMEOUT(408, "Request Timeout"),
CONFLICT(409, "Conflict"),
GONE(410, "Gone"),
LENGTH_REQUIRED(411, "Length Required"),
PRECONDITION_FAILED(412, "Precondition Failed"),
PAYLOAD_TOO_LARGE(413, "Payload Too Large"),
/** @deprecated */
@Deprecated
REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"),
URI_TOO_LONG(414, "URI Too Long"),
/** @deprecated */
@Deprecated
REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"),
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested range not satisfiable"),
EXPECTATION_FAILED(417, "Expectation Failed"),
I_AM_A_TEAPOT(418, "I'm a teapot"),
/** @deprecated */
@Deprecated
INSUFFICIENT_SPACE_ON_RESOURCE(419, "Insufficient Space On Resource"),
/** @deprecated */
@Deprecated
METHOD_FAILURE(420, "Method Failure"),
/** @deprecated */
@Deprecated
DESTINATION_LOCKED(421, "Destination Locked"),
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),
LOCKED(423, "Locked"),
FAILED_DEPENDENCY(424, "Failed Dependency"),
UPGRADE_REQUIRED(426, "Upgrade Required"),
PRECONDITION_REQUIRED(428, "Precondition Required"),
TOO_MANY_REQUESTS(429, "Too Many Requests"),
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),
UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
NOT_IMPLEMENTED(501, "Not Implemented"),
BAD_GATEWAY(502, "Bad Gateway"),
SERVICE_UNAVAILABLE(503, "Service Unavailable"),
GATEWAY_TIMEOUT(504, "Gateway Timeout"),
HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version not supported"),
VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"),
INSUFFICIENT_STORAGE(507, "Insufficient Storage"),
LOOP_DETECTED(508, "Loop Detected"),
BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded"),
NOT_EXTENDED(510, "Not Extended"),
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required");
private final int value;
private final String reasonPhrase;
private HttpStatus(int value, String reasonPhrase) {
this.value = value;
this.reasonPhrase = reasonPhrase;
}
public int value() {
return this.value;
}
public String getReasonPhrase() {
return this.reasonPhrase;
}
public boolean is1xxInformational() {
return HttpStatus.Series.INFORMATIONAL.equals(this.series());
}
public boolean is2xxSuccessful() {
return HttpStatus.Series.SUCCESSFUL.equals(this.series());
}
public boolean is3xxRedirection() {
return HttpStatus.Series.REDIRECTION.equals(this.series());
}
public boolean is4xxClientError() {
return HttpStatus.Series.CLIENT_ERROR.equals(this.series());
}
public boolean is5xxServerError() {
return HttpStatus.Series.SERVER_ERROR.equals(this.series());
}
public boolean isError() {
return this.is4xxClientError() || this.is5xxServerError();
}
public HttpStatus.Series series() {
return HttpStatus.Series.valueOf(this);
}
public String toString() {
return Integer.toString(this.value);
}
public static HttpStatus valueOf(int statusCode) {
HttpStatus status = resolve(statusCode);
if (status == null) {
throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
} else {
return status;
}
}
@Nullable
public static HttpStatus resolve(int statusCode) {
HttpStatus[] var1 = values();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
HttpStatus status = var1[var3];
if (status.value == statusCode) {
return status;
}
}
return null;
}
}
该类并不复杂,通过思维导图简单的阐述
恍然大悟,原来枚举对象也可以有自己的成员,这本身就更加的符合面向对象的思想。而而这些错误码可以继续分类成五种类型,
在代码中把这些类型构建成了静态内部类,即HttpStatus.Series类。具体源码如下:
public static enum Series {
INFORMATIONAL(1),
SUCCESSFUL(2),
REDIRECTION(3),
CLIENT_ERROR(4),
SERVER_ERROR(5);
private final int value;
private Series(int value) {
this.value = value;
}
public int value() {
return this.value;
}
public static HttpStatus.Series valueOf(int status) {
int seriesCode = status / 100;
HttpStatus.Series[] var2 = values();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
HttpStatus.Series series = var2[var4];
if (series.value == seriesCode) {
return series;
}
}
throw new IllegalArgumentException("No matching constant for [" + status + "]");
}
public static HttpStatus.Series valueOf(HttpStatus status) {
return valueOf(status.value);
}
}
因为Http请求响应码一共有五种,因此一共有5个该类型对象,通过私有化构造器,不允许创建新的系列。并不复杂,不在此赘述了。
关于具体的Http响应码的含义阐述可以参见博客Http错误码从1 到5 详解进行更加准确的理解。
3关于枚举实现接口
关于让枚举类实现接口这个内容,用的很少,暂时贴一下代码,很容易就可以理解,如下的代码通过匿名内部类实现了接口完成了对象的多态展示。代码出处Java 枚举:实现接口
package mark.demo;
public class EnumDemo {
public static void main(String[] args) {
for (Color color : Color.values()) {
color.setColor();
color.setType();
}
}
interface Paint {
public void setColor();
public void setType();
}
public enum Color implements Paint {
RED("red color", 0) {
@Override
public void setColor() {
System.out.println("Current paint color: " + RED._name);
}
@Override
public void setType() {
System.out.println("Current paint type: " + "5");
}
},
GREEN("green color", 1) {
@Override
public void setColor() {
System.out.println("Current paint color: " + GREEN._name);
}
@Override
public void setType() {
System.out.println("Current paint type: " + "1");
}
},
BLUE("blue color", 2) {
@Override
public void setColor() {
System.out.println("Current paint color: " + BLUE._name);
}
@Override
public void setType() {
System.out.println("Current paint type: " + "12");
}
},
YELLOW("yellow color", 3) {
@Override
public void setColor() {
System.out.println("Current paint color: " + YELLOW._name);
}
@Override
public void setType() {
System.out.println("Current paint type: " + "80");
}
};
Color(String name, int id) {
_name = name;
_id = id;
}
private String _name;
private int _id;
public String getName() {
return _name;
}
public int getId() {
return _id;
}
}
}
3总结
本博客整体思路如下图所示
对于枚举的使用掌握上述代码中使用的技巧,在很多场景下都足以应对我们的编程问题。HttpStatus类的实现很精彩,读者可以深入研究一下好好理解具体实现的过程。
2019-03-23 20:49于南京大学鼓楼校区207