优化java代码的一些小技巧(二)————常量尽量使用枚举

本文探讨了在Java中使用枚举替代基本数据类型作为常量的优势,包括增强的参数校验、内置方法调用及代码可读性的提升。通过HTTP响应代码的例子,详细比较了枚举与静态final常量的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2、常量尽量使用枚举

    需要用户列出一组预定义或常量值的场景有很多,例如在web应用程序中可能遇到的HTTP响应代码。最常见的实现技术之一是新建类,该类里面有很多静态的final类型的值,每个值都应该有一句注释,描述该值的含义是什么。例如:

public class HttpResponseCodes {  
    public static final int OK = 200;  
    public static final int NOT_FOUND = 404;  
    public static final int FORBIDDEN = 403;  
}  
if (getHttpResponse().getStatusCode() == HttpResponseCodes.OK) {  
    // Do something if the response code is OK   
}  

    能够有这种思路就已经非常好了,但这还是有一些缺点:     

  • 没有对传入的整数值进行严格的校验
  • 由于是基本数据类型,因此不能调用状态代码上的方法

    用静态final常量只是简单的创建了一个特定的常量来表示特殊的整数值,但并没有对方法或变量进行限制,因此使用的值可能会超出定义的范围。例如: 

public class HttpResponseHandler {  
    public static void printMessage(int statusCode) {  
        System.out.println("Recieved status of " + statusCode);   
    }  
}  
HttpResponseHandler.printMessage(15000);  

    尽管15000并不是有效的HTTP响应代码,但是,由于服务器端也没有限制客户端必须提供有效的整数。所以,我们没有办法为状态代码定义方法。

    例如,如果想要检查给定的状态代码是否是一个成功的代码,那就必须定义一个单独的函数: 

public class HttpResponseCodes {  
    public static final int OK = 200;  
    public static final int NOT_FOUND = 404;  
    public static final int FORBIDDEN = 403;  
    public static boolean isSuccess(int statusCode) {  
        return statusCode >= 200 && statusCode < 300;   
    }  
}  
if (HttpResponseCodes.isSuccess(getHttpResponse().getStatusCode())) {  
    // Do something if the response code is a success code   
}  

    再看看以下的解决方法。

    我们将常量类型从基本数据类型改为自定义类型,并只允许自定义类的特定对象。这正是Java枚举(enum)的用途。使用enum,我们可以一次性解决参数校验方法调用的问题: 

public enum HttpResponseCodes {  
    OK(200),  
    FORBIDDEN(403),  
    NOT_FOUND(404);  
    private final int code;   
    HttpResponseCodes(int code) {  
        this.code = code;  
    }  
    public int getCode() {  
        return code;  
    }  
    public boolean isSuccess() {  
        return code >= 200 && code < 300;  
    }  
}  
if (getHttpResponse().getStatusCode().isSuccess()) {  
    // Do something if the response code is a success code   
}  

    现在还可以要求在调用方法的时候提供必须有效的状态代码: 

public class HttpResponseHandler {  
    public static void printMessage(HttpResponseCode statusCode) {  
        System.out.println("Recieved status of " + statusCode.getCode());   
    }  
}  
HttpResponseHandler.printMessage(HttpResponseCode.OK); 

    注意,举这个例子是想说明如果是常量,则应该尽量使用枚举,但并不是说什么情况下都应该使用枚举

    在某些情况下,可能希望使用一个常量来表示某个特殊值,但是也允许提供其它的值。例如,大家可能都知道圆周率,我们可以用一个常量来捕获这个值(并重用它): 

public class NumericConstants {  
    public static final double PI = 3.14;  
    public static final double UNIT_CIRCLE_AREA = PI * PI;  
}  
public class Rug {  
    private final double area;  
    public class Run(double area) {  
        this.area = area;  
    }  
    public double getCost() {  
        return area * 2;  
    }  
}  
// Create a carpet that is 4 feet in diameter (radius of 2 feet)  
Rug fourFootRug = new Rug(2 * NumericConstants.UNIT_CIRCLE_AREA); 

    使用枚举的规则可以归纳为: 

    当所有可能的离散值都已经提前知道了,那么就可以使用枚举

    再拿上文中所提到的HTTP响应代码为例,我们可能知道HTTP状态代码的所有值(可以在RFC 7231中找的到,它定义了HTTP 1.1协议)。因此使用了枚举。

    在计算圆周率的情况下,我们不知道关于圆周率的所有可能值(任何可能的double都是有效的),但同时又希望为圆形的rugs创建一个常量,使计算更容易(更容易阅读);因此定义了一系列常量。 

    如果不能提前知道所有可能的值,但是又希望包含每个值的字段或方法,那么最简单的方法就是可以新建一个类来表示数据。

    尽管没有说过什么场景应该绝对不用枚举,但要想知道在什么地方、什么时间不使用枚举的关键是提前意识到所有的值,并且禁止使用其他任何值。

转载于:https://my.oschina.net/fl128818/blog/1550489

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值