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));
        }
    }
  • 相关阅读:
    计算机二级-C语言-程序修改题-190114记录-对整型变量进行取余操作可以取得各个位上的值。
    计算机二级C语言选择题错题知识点记录。
    计算机二级-C语言-对文件的读写操作。链表的定义与赋值。对字符串的遍历和处理。
    二十七、Java基础之数组的排列
    二十六、Java语言之二维数组
    二十五、Java基础之一维数组
    二十四、Java基础之自定义异常
    二十三、Java基础之异常及异常处理机制
    二十二、Java基础之内部类
    二十一、Java基础之访问控制权限
  • 原文地址:https://www.cnblogs.com/EvanLiu/p/3143427.html
Copyright © 2011-2022 走看看