枚举

Java1.5之后,有了enum关键字,定义枚举类。它是一种特殊的类,同样可以有方法和属性,可以实现一个或多个接口,可以定义构造器。它与普通类区别:

1.枚举类可实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是Object类。而java.lang.Enum类实现了java.lang.Serializablejava.lang.Comparable两个接口。

2.枚举类的构造器只能使用private访问控制符,省略则默认为private,指定也只能指定private

3.枚举类的所有实例必须在枚举类中显式列出。系统自动添加public static final修饰符。

4.所有枚举类都提供了一个values方法,方便遍历所有的枚举值。

使用enum关键字创建EnumSeason,如下:

enum EnumSeason  {
   SPRING, SUMMER, FALL, WINTER
}


替代使用String定义常量:

public class EnumSeason  {
   public static final String SPRING = “SPRING”;
   public static final String SUMMER = “SUMMER”;
   public static final String FALL = “FALL”;
   public static final String WINTER = “WINTER”; 
}


由于使用字符串常量这种方式是编译时常量,即在.java文件在编译成.class时,会把这些常量替换为相应的值。这样其他的类里有引用到的时候也会被替换,如果字符串常量发生改变了,那么其他的类也要重新进行编译。而枚举是运行时,枚举类改变后,只需要重新编译枚举类即可。

使用枚举类:


public static void main(String[] args) {
    judge(EnumSeason.SPRING);
    for (EnumSeason s : EnumSeason.values()) {
        System.out.println(s.ordinal() + ":" + s);
    }
}
public static void judge(EnumSeason season) {
    switch (season) {
        case SPRING:
            System.out.println("春暖花开");
            break;
        case SUMMER:
            System.out.println("夏日温情");
            break;
        case FALL:
            System.out.println("秋高气爽");
            break;
        case WINTER:
            System.out.println("东风瑟瑟");
        default:
            System.out.println("什么呀这是");
    }
}


运行结果如下:

春暖花开

0:SPRING

1:SUMMER

2:FALL

3:WINTER

为枚举类添加属性,如下:

enum Gender {
    MALE, FEMALE;
    public String name;
}

使用如下:

Gender g = Enum.valueOf(Gender.class, "FEMALE");
g.name = "女";
System.out.println(g + "代表:" + g.name);

Enum类的静态方法valueOf(Class,  String)

上面直接访问enum属性的方式不太安全,可以改为添加setter/getter方法:

enum Gender {
    MALE, FEMALE;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        switch(this) {
        case MALE:
            if("男".equals(name)){
                this.name = name;
            } else {
                System.out.println("参数错误");
                return;
            }
            break;
        case FEMALE:
            if("女".equals(name)){
                this.name = name;
            } else {
                System.out.println("参数错误");
                return;
            }
            break;
        }
    }
}

主函数如下:

Gender g = Enum.valueOf(Gender.class, "FEMALE");
g.setName("女");
System.out.println(g + "代表:" + g.getName());

g.setName("男"); //参数错误
System.out.println(g + "代表:" + g.getName());

这种方法仍不够科学,因为枚举类通常设计成不可变类,即属性值不允许修改,这样更安全,因此应该把枚举类的属性都使用private final修饰。可使用private构造函数方式,如下:

enum Gender {
    MALE("男"), FEMALE;
    private final String name;
    
    private Gender(String name) {
        this.name = name;
    }
}

Enum枚举实现接口,例子如下:因为有了构造函数,因此枚举变量中每个值都得使用构造函数方式,因此MALE("男")没有问题,而FEMALE就编译通不过,因为没有无参的构造函数。

interface InterfaceForEnum {
    public void fun();
}

enum EmotionEnum implements InterfaceForEnum{
    HAPPY, ANGRY;

    @Override
    public void fun() {
        System.out.println("I'm an emotion");
    }
}

这种方式,每个枚举值调用fun()方法时,行为就一样了,没能达到接口效果,可改为如下:

enum EmotionEnum implements InterfaceForEnum{
    HAPPY {
        public void fun() {
            System.out.println("I'm very happy");
        }
    }
    , ANGRY {

        @Override
        public void fun() {
            System.out.println("I'm angry");
        }
    }
}

同样,也可以在enum中定义抽象方法,这样每个枚举值都得实现该抽象方法。

enum EmotionEnum {
    HAPPY {
        public int evel(int n1, int n2) {
            return n1 - n2;
        }
    }
    , ANGRY {
        
        public int evel(int n1, int n2) {
            return n1 + n2;
        }
    };
    
    public abstract int evel(int n1, int n2);
}

同时,使用枚举实现单例模式,可以实现单例模式,并且可以防止通过反射和序列化方式破解单例

public enum Singleton {
    INSTANCE;

    public void method1() {
        System.out.println("hello");
    }
}

你可能感兴趣的:(枚举)