疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java枚举类的Field,方法和构造器


 

 
 
枚举类也是一种类,只是它是一种比较特殊的类,因此它一样可以定义Field,方法。下面程序定义一个Gender枚举类,该枚举类里包含了一个name实例变量。
 
public enum Gender {
    MALE, FEMALE;
    // 定义一个public修饰的实例变量
    public String name;
}
上面的Gender枚举类里定义了一个名为name的实例变量,并且将它定义成一个public访问权限的。下面通过如下程序来使用该枚举类。
 
public class GenderTest {
    public static void main(String[] args) {
        // 通过Enum的valueOf方法来获取指定枚举类的枚举值
        Gender g = Enum.valueOf(Gender.class, "FEMALE");
        // 直接为枚举值的Field赋值
        g.name = "女";
        // 直接访问枚举值的Field值
        System.out.println(g + "代表:" + g.name);
    }
}
上面程序使用Gender枚举类时与使用一个普通类没有太大的差别,差别只是产生Gender对象的方式不同,枚举类的实例只能是枚举值,而不是随意的通过new来创建枚举类对象。
 
Java应该把所有的类设计成良好封装的类,所以不应该直接访问Gender类的name成员变量,而是应该通过方法来控制对name的访问。否则可能出现混乱的情形,例如上面程序,恰好我们设置了g.name="女",要是采用g.name="男",那程序就会非常混乱了,可能出现FEMALE代表男的局面。为此改进Gender类的设计如下:
 
public enum Gender {
    MALE, FEMALE;
    private String name;
 
    public void setName(String name) {
        switch (this) {
        case MALE:
            if (name.equals("男")) {
                this.name = name;
            } else {
                System.out.println("参数错误");
                return;
            }
            break;
        case FEMALE:
            if (name.equals("女")) {
                this.name = name;
            } else {
                System.out.println("参数错误");
                return;
            }
            break;
        }
    }
 
    public String getName() {
        return this.name;
    }
}
上面程序把name设置成private,从而避免其他程序直接访问该name成员变量,必须通过setName()方法来修改Gender实例的name变量,而setName()方法就可以保证不会产生混乱。上面程序保证FEMALE枚举值的name变量只能设置为”女”,而MALE枚举值的name变量则只能设置为”男”,看下面的程序:
public class GenderTest
{
    public static void main(String[] args) 
    {
        Gender g = Enum.valueOf(Gender.class , "FEMALE");
        g.setName("女");
        System.out.println(g + "代表:" + g.getName());
        //此时设置name值时将会提示参数错误。
        g.setName("男");
        System.out.println(g + "代表:" + g.getName());
    }
}
上面代码中,g.setName(“男”)试图把一个FEMALE枚举值的name变量设置为”男”,系统将会提示参数错误。
 
实际上这种做法依然不够好,枚举类通常应该设计成为不可变类,也就是说,它的Field值不应该允许改变,这样会更加安全,而且代码更加简洁。为此,应该将枚举类的Field都使用private final修饰。
 
因为将所有的Field都使用了final修饰符来修饰,所以必须在构造器里为这些Field指定初始值(或者在定义Field时指定默认值,或者在初始化块中指定初始值,但是这两种情况并不常见),因此,应该为枚举类显示定义带参数的构造器。一旦为枚举类显示定义了带参数的构造器,列举枚举值时就必须对应地传入参数。
 
public enum Gender
{
    //此处的枚举值必须调用对应构造器来创建
    MALE("男"),FEMALE("女");
    private final String name;
    //枚举类的构造器只能使用private修饰
    private Gender(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return this.name;
    }
}
从上面程序可以看出,当为Gender枚举类创建了一个Gender(String name)构造器之后,列出枚举值就应该采用MALE("男"),FEMALE("女");这种代码来完成。也就是说,在枚举类中列出枚举值时,实际上就是调用构造器创建枚举类对象,只是这里无须使用new关键字,也无须显式调用构造器。前面列出枚举值时无须传入参数,甚至无须使用括号,仅仅是因为前面的枚举类包含无参数的构造器。不难看出,上面程序中的代码MALE("男"),FEMALE("女");实际上等同于如下两行代码:
 
public static final Gender MALE = new Gender("男");
public static final Gender FEMALE = new Gender("女");