常量定义在接口还是类中?

1. 前言

最近看项目的时候发现,这个项目把常量定义在接口当中,感觉到很神奇,随之我就想到了一个问题,竟然常量可以定义到接口里,也可以定义到类和枚举中,哪到底哪个更合适一点,于是我上网查了一些资料。得出一下结论

2. 解析

public interface Constants{
   int USER_EROOR = 1;
   int USER_EROOR_PASS = 2;
}
public class Constants{
   public static final int USER_EROOR = 1;
   public static final int USER_EROOR_PASS = 2;
}
@Getter
@AllArgsConstructor
public enum ChildType {
    NORMAL_PARENT(0, "正规课"),
    TRIAL_PARENT(1, "体验课");

    private int id;
    private String name;
}

相比较第一种和第二种其实差不多,但第一种显然更简洁,因为不用写 public static final 了嘛,更方便了。但是,但是,但是不建议在接口中定义常量。因为我在阅读《Effective Java》这本书中提到过:

如果某个实现了常量接口的类被修改不再需要常量了,也会因为序列化兼容原因不得不保持该实现,而且非final类实现常量接口会导致所有子类被污染

示例

interface Drawable {

    double GOLDEN_RATIO = 1.618033988;
    double PI = 3.141592653;
    ...

    // methods
    ...
}

public class Circle implements Drawable {
    ...
    public double getCircumference() {
        return 2 * PI * r;
    }
}

void usage() {

    Circle circle = new Circle(radius: 3.0);
    double maxRadius = 5.0;

    if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
        ...
    }

}

推荐:接口中的常量, 不应该用于全局. 而应当用在与之相关的类中。这样能保持很好的层级关系和隔离性,方便分包和扩展,具体请参考spring中对常量维护的原则。

当然,刚才说了不建议把一般的常量放在接口里,所以我们可以放在常量类了,但建议常量类是final的。

什么时候使用枚举呢?其实建议使用枚举。《Effective Java》中也是推荐使用枚举代替int常量的。 枚举当然是首选,另如果不用枚举,在《Effective Java》一书中,作者建议使用一般类加私有构造方法的方式,至于为什么不用接口,那就要上升到语言哲学问题了(可参考上面通俗易懂的话)。

此处个人不建议什么都使用枚举来代替常量类。比如毫无规则归类可言的一些常量:如SUCCUSS字符串、密钥串、路径等等这些,可以放在一个常量类里面糅在一起。而对于数据库中对应type、status类型字段并且是可以枚举出来的,强烈建议使用enum类型,在平时获取、使用、校验起来常量无法比拟的,而且可以很少犯错,非常大程度上增加代码的可读性,这也是为什么JDK5要推荐使用枚举类的原因吧。

最后,本人建议大家可以在设计代码的时候,多用接口规范代码,哪怕只是一个标记接口,也尽量为了长远考虑而设计出来。通过读spring、mybatis源码会发现里面不乏一些标记接口,在向上抽象归类判断的时候,非常有用。

posted @ 2023-08-17 15:01  ゐ叶う枫ゆ  阅读(270)  评论(0编辑  收藏  举报