《疯狂Java讲义》(十六)---- 枚举类

Posted coder为

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《疯狂Java讲义》(十六)---- 枚举类相关的知识,希望对你有一定的参考价值。

  •  枚举类与普通类的区别
    •  枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承java.lang.Enum类,而不是java.lang.Object类,其中java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
    •    使用enum定义,非抽象的枚举类默认会使用final修饰,因此枚举类不能派生子类。
    •    枚举类的构造器只能使用private访问控制符
    •    枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。
    •    枚举类都提供了一个values方法,该方法可以很方便地遍历所有的枚举值。

 

enum SeasonEnum {
    SPRING, SUMMER, FALL, WINTER;
}

public class EnumTest {

    public void judge(SeasonEnum s) {
        switch (s) {
            case SPRING:
                System.out.println("Spring is comming");
                break;
            case SUMMER:
                System.out.println("Summer is comming");
                break;
            case FALL:
                System.out.println("Fall is comming");
                break;
            case WINTER:
                System.out.println("Winter is comming");
                break;
            default:
                System.out.println("not exist season");
        }
    }

    public static void main(String[] args) {
        for (SeasonEnum s : SeasonEnum.values()) {
            System.out.println(s);
        }

        new EnumTest().judge(SeasonEnum.SPRING);

    }

}

 

  • 枚举类的Field/方法/构造函数

    枚举类一样可以定义Field和方法。也可以将field访问符设置为public,直接修改值,但这样破坏了类的封装性。也可以将field访问符改为private,提供getter和setter,但是通常枚举类应该设计成不可变类。

    枚举类的field值不应该允许改变,这样会更安全,而且代码也简洁。所以,枚举类的field都使用private final修饰。所以必须在构造器里为这些Field指定初始值(或载定义field时指定默认值, 在初始化块中指定初始值,但这两种情况并不常见),因此应该为枚举类显式定义带参数的构造器。一旦为枚举类显式定义了带参数的构造器,在第一行列出枚举实例时就必须对应的传入参数。

public enum Gender {

    MALE("nan"), FEMALE("nv");
    
    private final String name;
    
    private Gender(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }
}

  在枚举类中列出枚举值时,实际上就是调用构造器创建枚举类对象,只是这里无须使用new关键字,也无须显式调用构造器。上一个例子中列出枚举值时没有传入参数,仅仅是因为前面的枚举类包含无参数的构造器。

  MALE("nan") 相当于 public static final Gender MALE = new Gender("nan");

 

  • 实现接口的枚举类
interface GenderDesc {
    void info();
}
public enum Gender2 implements GenderDesc{
    MALE, FEMALE;

    @Override
    public void info() {
        // TODO Auto-generated method stub
        
    }

}

如果由枚举类来实现接口里的方法,则每个枚举类在调用该方法时都有相同的行为方式。如果需要每个枚举值在调用该方法时呈现不同的行为方式,则可以让每个枚举值分别来实现该方法

interface GenderDesc {
    void info();
}
public enum Gender2 implements GenderDesc{
    MALE {

        @Override
        public void info() {
            // TODO Auto-generated method stub
            
        }
    }, FEMALE {
        
        @Override
        public void info() {
            // TODO Auto-generated method stub
            
        }
    };

}

上边的情况中, 当创建MALE/FAMALE枚举值,并不是直接创建Gender枚举类的实例,而是相当于创建Gender的匿名子类的实例。

编译上边程序,生成Gender.class, Gender$1.class, Gender$2.class三个文件,证明MALE和FEMALE实际上是Gender匿名子类的实例,而不是Gender类的实例。

 

提问:枚举类不是用final修饰了吗?怎么还能派生子类呢?

回答:并不是所有的枚举类都是用了final修饰符,非抽象的枚举类才默认是用final修饰。对于一个抽象的枚举类而言 -- 只要它包含了抽象方法,它就是抽象枚举类,系统会默认是用abstract修饰,而不是final。

 

  • 包含抽象方法的枚举类
public enum Operation {

    PLUS {
        public double eval(double x, double y) {
            return x + y;
        }
    },
    MINUS {
        public double eval(double x, double y) {
            return x - y;
        }
    },
    TIMES {
        public double eval(double x, double y) {
            return x * y;
        }
    },
    DIVIDE {
        public double eval(double x, double y) {
            return x / y;
        }
    };
    public abstract double eval(double x, double y);
    
    public static void main(String[] args) {
        System.out.println(Operation.PLUS.eval(3, 4));
        System.out.println(Operation.MINUS.eval(3, 4));
        System.out.println(Operation.TIMES.eval(3, 4));
        System.out.println(Operation.DIVIDE.eval(3, 4));
    }
}

 枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类(因为系统会自动为它添加abstract),但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则编译错误。

 

以上是关于《疯狂Java讲义》(十六)---- 枚举类的主要内容,如果未能解决你的问题,请参考以下文章

疯狂Java讲义(十四)---- 抽象类和接口

《疯狂Java讲义》读书笔记4

疯狂Java讲义-读书笔记1.5 第一个Java程序

读《疯狂Java讲义》笔记总结三

疯狂Java讲义---- 初始化块

疯狂Java讲义-读书笔记1.6 Java程序的基本规则