zoukankan      html  css  js  c++  java
  • 《疯狂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),但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则编译错误。

  • 相关阅读:
    maven -- 问题解决(四)警告Classpath entry org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER will not be exported or published
    maven -- 问题解决(三)Java compiler level does not match the version of the installed Java project facet
    mybatis学习笔记(四)-- 为实体类定义别名两种方法(基于xml映射)
    mybatis学习笔记(三)-- 优化数据库连接配置
    mybatis学习笔记(二)-- 使用mybatisUtil工具类体验基于xml和注解实现
    mybatis学习笔记(一)-- 简单入门(附测试Demo详细过程)
    c# -- 解决vs使用本地iis运行项目支持局域网访问的问题(附防火墙端口开放步骤)
    sqlserver -- 查看当前数据库的数据表(备忘)
    sqlserver -- 解决sqlserver2008“Prevent saving changes that require table re_creation(阻止保存要求重新创建表的更改)”的问题
    关于mysql 5.7版本“报[Err] 1093
  • 原文地址:https://www.cnblogs.com/IvySue/p/6343763.html
Copyright © 2011-2022 走看看