在JAVA的使用过程中,我们经常会需要用到一些常量。那么我们要怎么去定义这些常量呢?(通常指的是一组数量有限的常量)
接口中定义常量
采用接口(Interface)中变量默认为static final的特性。
public interface ConstantInterface {
String SUNDAY = "SUNDAY";
String MONDAY = "MONDAY";
String TUESDAY = "TUESDAY";
String WEDNESDAY = "WEDNESDAY";
String THURSDAY = "THURSDAY";
String FRIDAY = "FRIDAY";
String SATURDAY = "SATURDAY";
}
这种方式虽然看起来比较简单,不用写太多的修饰词,而且也比较灵活(比如可以直接赋想要的值,就算是中文也可以),但是由于接口可以被实现,会导致实现类被污染。因此这种方式并不推荐使用。
普通类中定义常量
采用了在普通类中使用static final修饰变量的方法。
public class ConstantClassField {
public static final String SUNDAY = "SUNDAY";
public static final String MONDAY = "MONDAY";
public static final String TUESDAY = "TUESDAY";
public static final String WEDNESDAY = "WEDNESDAY";
public static final String THURSDAY = "THURSDAY";
public static final String FRIDAY = "FRIDAY";
public static final String SATURDAY = "SATURDAY";
}
此时这些常量需要是public的,否则不能被其他地方使用。当然也可以使用get方法。
public class ConstantClassFunction {
private static final String SUNDAY = "SUNDAY";
private static final String MONDAY = "MONDAY";
private static final String TUESDAY = "TUESDAY";
private static final String WEDNESDAY = "WEDNESDAY";
private static final String THURSDAY = "THURSDAY";
private static final String FRIDAY = "FRIDAY";
private static final String SATURDAY = "SATURDAY";
public static String getSunday() {
return SUNDAY;
}
public static String getMonday() {
return MONDAY;
}
public static String getTuesday() {
return TUESDAY;
}
public static String getWednesday() {
return WEDNESDAY;
}
public static String getThursday() {
return THURSDAY;
}
public static String getFirday() {
return FRIDAY;
}
public static String getSaturday() {
return SATURDAY;
}
}
如果是这样,仍然会面临污染子类的问题,因此可以让该类成为final类,使其不能被继承。
public final class ConstantClassField {
public static final String SUNDAY = "SUNDAY";
public static final String MONDAY = "MONDAY";
public static final String TUESDAY = "TUESDAY";
public static final String WEDNESDAY = "WEDNESDAY";
public static final String THURSDAY = "THURSDAY";
public static final String FRIDAY = "FRIDAY";
public static final String SATURDAY = "SATURDAY";
}
还可以结合内部类使用,限制它的使用范围。如果是进行常量管理,我个人觉得这种方式更好用一些,因为更加灵活,你可以给每个变量直接赋你想要的值。
Enum定义常量
enum ConstantEnum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
先大概了解一下枚举:枚举是JDK1.5出现的新特性。所有的枚举类都隐性地继承自java.lang.Enum类(因此不能再继承其他的任何类),枚举本质上还是个class, 而每个被枚举的成员就是一个枚举类型的实例(具体实现中相当于是new了对应个数的当前对象),他们默认都是static final修饰的,可以直接通过枚举名使用他们。
由于Enum类重写了toString方法,所以直接使用的话会输出枚举对象名(可以用在switch语句中),因此枚举项才可以被当做一组常量。但是当我需要一组中文常量时,就显得有些不那么简洁了,因为此时我就需要给这些对象赋值。
所以,如果是直接几个常量的定义,并且这些常量是满足java命名规则的,那么推荐使用枚举。但如果有时真的需要使用枚举,并且要给这些对象赋予一些对应的值呢?
其实就和普通类类似,无非就是想办法给该类的对象赋值的过程。通常可以直接在当前枚举类中定义成员变量和构造方法来进行初始化,然后定义get方法来获取对应的值,当然还可以定义set方法来重新赋值,跟普通类几乎一模一样。比如要获取季节对应的中文。
public enum SeasonEnum {
//枚举类的实例对象必须在最前面先定义,而且必须每个实例对象都必须维护上chinese成员变量
SPRING("春天"),SUMMER("夏天"),AUMUTN("秋天"),WINTER("冬天"); // 这里的分号别忘了
private String chinese;
//枚举类型的构造函数默认为private,因为枚举类型的初始化要在当前枚举类中完成。
SeasonEnum (String chinese){
this.chinese= chinese;
}
public String getChinese(){
return chinese;
}
}
像这样通过括号赋值需要有一个带参构造器、一个属性跟对应的方法,否则编译出错 ;赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,否则编译也会出错。
然后就和普通对象一样使用
public class Test{
public static void main(String[] args) {
//直接初始化
SeasonEnum season = SeasonEnum.SPRING;
//调用SeasonEnum枚举类的getChinese()方法获取SPRING的中文值
System.out.println(season.getChinese());
}
}
另外还可以使用匿名类的方式来定义对应的方法(这种方式其实并不好,代码重复度有些高,不过很直接)
public enum SeasonEnum {
SPRING{
String getSeason(){
return "春天";
}
},
SUMMER("夏天"){
String getSeason(){
return "夏天";
}
},
AUMUTN("秋天"){
String getSeason(){
return "秋天";
}
},
WINTER("冬天"){
String getSeason(){
return "冬天";
}
};
// 枚举类中的抽象方法,然后匿名类才能覆盖重写
String getSeason();
}
补充
1、明明可以直接写值,为什么非要把常量提取出来定义呢?比如我就直接写1、直接写"str",不也行吗?当然可以,这其实和性能没有太大关系,主要是代码规范的问题,比如避免魔鬼数字、提高可读性等。
2、什么时候需要用到这样的方式来定义常量呢?通常如果有一组固定数量的常量需要被用到时就可以这么做。要注意的是,其实完全可以在要使用这些常量的类中成员位置定义这些常量,为什么还要独立出来呢?这其实是为了方便管理常量,而且也很容易实现共享。
3、从第二点来看,类中成员位置的常量都是可以被独立出来进行管理的,比如按照类型功能等进行分类定义。但是如果某个类只是临时用到一两个常量,并且这些常量并没有可能被其他地方所引用,那么就没有必要独立出来进行管理了,直接在类成员位置定义即可,这样也更加方便。