zoukankan      html  css  js  c++  java
  • Java笔记:枚举类

    1.一个类的实例是有限且固定的,这个类称为枚举类。比如季节类,只有四个对象(春、夏、秋、冬)

    2.手动实现一个枚举类
    (1)通过private将构造器隐藏起来
    (2)把这个类的所有可能实例都使用private static final修饰的类变量来保存。
    (3)如果有必要,可以提供一些静态方法。

    package cn.it.lsl;
    
    public class Season {
        private final String name;
        private final String desc;
        private Season(String name, String desc){
            this.name = name;
            this.desc = desc;
        }
        public static final Season SPRING = new Season("春天","踏青");
        public static final Season SUMMER = new Season("夏天","夏日炎炎");
        public static final Season FAIL = new Season("秋天","秋高气爽");
        public static final Season WINTER = new Season("冬天","白雪皑皑");
        
        public String getName(){
            return this.name;
        }
        public String getDesc(){
            return this.desc;
        }
    }
    package cn.it.lsl;
    
    public class SeasonTest {
        public SeasonTest(Season s){
            System.out.println(s.getName() + "," + s.getDesc());
        }
        public static void main(String[] args) {
            new SeasonTest(Season.FAIL);
        }
    }

    Season类是一个不可变类。Season类中包含了4个static final常量的Field,这4个常量Field就代表了该类所能创建的对象。当程序需要调用Season对象时,就可以通过Season.SPRING的方式来取得Season对象。

    这里顺便复习一下不可变类
    不可变类:创建该类的实例后,该实例的Field是不可改变的。
    如果要创建自定义的不可变类,需遵循如下规则:
    (1)使用private和final修饰符来修饰该类的Field。
    (2)提供带参数的构造函数,用于根据传入参数来初始化类里的Field。
    (3)仅为该类的Field提供getter方法,不要为该类的Field提供setter方法。
    (4)如果有必要,重写Object类的hashCode和equals方法。

    3.枚举类
    (1)使用enum关键字定义枚举类。枚举类一样可以有自己的Field、方法,可以实现一个或多个接口,也可以有自己的构造器。
    (2)使用eunm定义的枚举类默认继承了java.lang.Enum类,而不是继承Object类。
    (3)使用enum定义、非抽象的枚举类默认会使用final修饰,因此枚举类不能派送子类。(并不是所有的枚举类都使用final修饰,如抽象枚举类)
    (4)枚举类所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远不能产生实例。
    (5)所有枚举类都提供一个values方法,该方法可以方便地遍历所有枚举值。

    package cn.lsl;
    
    public enum SeasonEnum {
        SPRING,SUMMER,FALL,WINTER;
    }
    package cn.lsl;
    
    public class EnumTest {
        
        public void judge(SeasonEnum s){
            switch(s){
                case SPRING:
                    System.out.println("春天");
                    break;
                case SUMMER:
                    System.out.println("夏天");
                    break;
                case FALL:
                    System.out.println("秋天");
                    break;
                case WINTER:
                    System.out.println("冬天");
                    break;
            }
        }
        public static void main(String[] args) {
            //列出所有枚举类的实例
            for(SeasonEnum s : SeasonEnum.values()){
                System.out.println(s);
            }
            
            new EnumTest().judge(SeasonEnum.FALL);
        }
    }

    4.枚举类的Field、方法

    枚举类可以定义自己的Field和方法。

    package cn.lsl;
    
    public enum Gender {
        MALE,FEMALE;
        public String name;
    }
    package cn.lsl;
    
    public class GenderTest {
        public static void main(String[] args) {
            //通过Enum的valueOf方法来获取指定枚举类的枚举值
            Gender g = Enum.valueOf(Gender.class, "FEMALE");
            g.name = "女";
            System.out.println(g + "," + g.name);
        }
    }

    在上面程序中产生Gender对象的方式与普通类不同,而是采用通过Enum的valueOf方法来获取指定枚举类的枚举值,枚举类的实例只能是枚举值,而不是随意通过new来创建的。

    其实上面程序中,没有实现java的良好封装,因为name的访问权限是public,这样就会出现随意对name赋值的情况,应该通过方法来控制对name的访问。

    改造上面的程序

    package cn.lsl;
    
    public enum Gender {
        MALE,FEMALE;
        public 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;
        }
    }
    package cn.lsl;
    
    public class GenderTest {
        public static void main(String[] args) {
            //通过Enum的valueOf方法来获取指定枚举类的枚举值
            Gender g = Enum.valueOf(Gender.class, "FEMALE");
            g.setName("女");
            System.out.println(g + "," + g.getName());
            g.setName("男");
            System.out.println(g + "," + g.getName());
        }
    }

    定义枚举类,以上的做法还是做的不够好,枚举类通常应该设计不可变类。其Field值不应该允许改变,这样会更安全。

    所以枚举类的Field都应该使用private final修饰。

    package cn.lsl;
    
    public enum Gender {
        MALE("男"),FEMALE("女");
        private final String name;
        private Gender(String name){
            this.name = name;
        }
        public String getName(){
            return this.name;
        }
    }

    5.实现接口的枚举类

    枚举类可以实现一个或多个接口。

    package cn.it.lsl;
    
    public interface GenderDesc {
        void info();
    }
    package cn.it.lsl;
    
    public enum Gender implements GenderDesc{
        MALE("男"),FEMALE("女");
        private final String name;
        private Gender(String name){
            this.name = name;
        }
        
        public String getName(){
            return this.name;
        }
    
        @Override
        public void info() {
            // TODO Auto-generated method stub
            System.out.println("枚举类实现接口");
        }
    
    }

    以上在枚举类里面实现接口的方法时,每个枚举值在调用该方法的时候都会有相同的行为(即方法体相同)。
    如果需要每个枚举值在调用该方法时表现出不同的行为方式,应该让每个枚举值分别实现该方法。

    package cn.it.lsl;
    
    public enum Gender implements GenderDesc{
        MALE("男"){
            public void info() {
                // TODO Auto-generated method stub
                System.out.println("枚举类实现接口,男");
            }
        },
        FEMALE("女"){
            public void info() {
                // TODO Auto-generated method stub
                System.out.println("枚举类实现接口,女");
            }
        };
        private final String name;
        private Gender(String name){
            this.name = name;
        }
        
        public String getName(){
            return this.name;
        }
    }

    6.包含抽象方法的枚举类

    在枚举类中定义抽象方法的时候不能使用abstract关键字将枚举类定义成抽象类(因为系统会自动为它添加abstract关键字),因为枚举类需要显示创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现。

    以下一个程序在枚举类中定义了一个抽象方法,这个抽象方法由不同的枚举值提供不同的实现

    package cn.it.lsl;
    
    public enum Operation {
        PLUS{
            @Override
            public double eval(double x, double y) {
                // TODO Auto-generated method stub
                return x + y;
            }
        },
        MINUS{
            @Override
            public double eval(double x, double y) {
                // TODO Auto-generated method stub
                return x - y;
            }
        },
        TIMES{
            @Override
            public double eval(double x, double y) {
                // TODO Auto-generated method stub
                return x * y;
            }
        },
        DIVIDE{
            @Override
            public double eval(double x, double y) {
                // TODO Auto-generated method stub
                return x / y;
            }
        };
        public abstract double eval(double x, double y);
        
        
        public static void main(String[] args) {
            System.out.println(Operation.PLUS.eval(2, 3));
            System.out.println(Operation.MINUS.eval(2, 3));
            System.out.println(Operation.TIMES.eval(2, 3));
            System.out.println(Operation.DIVIDE.eval(2, 3));
        }
    }
  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/EvanLiu/p/3143427.html
Copyright © 2011-2022 走看看