Java之枚举类

目录

一、为何引入枚举类型(为了替代魔法值)

1.静态常量类型不安全

2. 没有命名空间

二、枚举类型初识

1.enum和class、interface的地位一样 

2.比较同一枚举类中不同值直接= =

3.默认继承了java.lang.Enum

4.所有实例都必须放在第一行展示

5.不可以被继承

6.构造器只能是私有的

三、枚举类添加属性和构造器

四、枚举类实现接口

五、其他API

1. 返回指定名称和指定类的某个枚举类

2.返回枚举常量名

3.返回枚举常量的序数 

4.返回枚举的所有值


一、为何引入枚举类型(为了替代魔法值)

什么是魔法值?魔法值有哪些隐患,见另一篇文章编码规约之使用Enum枚举类替代魔法值

那么为什么不用静态变量来替换魔法值呢?

有时候,变量的取值只在一个有限的集合内。例如一年中只有春、夏、秋、冬四季,销售服装只有小、中、大、特大四种尺寸。当然,可以将这些尺寸分别编码为1、2、3、4或者S、M、L、X。可能,我们有疑问,为何不用静态全局常量来替代呢?以一年四季为例

    public static final int SEASON_SPRING = 1;
    public static final int SEASON_SUMMER = 2;
    public static final int SEASON_FALL = 3;
    public static final int SEASON_WINTER = 4;

但是这样存在着一定的隐患

1.静态常量类型不安全

若一个方法中要求传入季节这个参数,用常量的话,形参就是int类型,开发者传入任意类型的int类型值就行,但是如果是枚举类型的话,就只能传入枚举类中包含的对象。

currentSeason.setSeason(需要传入一个整型参数,即季节编码);

currentSeason.setSeason(SEASON_SPRING);//传入春季整型编码

//那既然setSeason接收一个整型数据,那么我就可以向其传入其他整型数据

currentSeason.setSeason(0);

//那么此处的0,又代表什么呢?

2. 没有命名空间

开发者要在命名的时候以SEASON_开头,这样另外一个开发者再看这段代码的时候,才知道这四个常量分别代表季节。

二、枚举类型初识

先看一个简单的枚举类

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

1.enum和class、interface的地位一样 

2.比较同一枚举类中不同值直接= =

因为枚举类型的值是固定的,不需要发生改变,在比较两个不同值时可以直接使用"= ="就可以了

3.默认继承了java.lang.Enum

enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类。但是,Enum是继承了Object类。枚举类可以实现一个或多个接口

4.所有实例都必须放在第一行展示

枚举类的所有实例都必须放在第一行展示,不需使用new 关键字,不需显式调用构造器。自动添加public static final修饰。

5.不可以被继承

使用enum定义、非抽象的枚举类默认使用final修饰,不可以被继承

6.构造器只能是私有的

因为枚举类型的值是固定的,不需要发生改变,因此枚举被设计成是单例模式。即枚举类型会由JVM在加载的时候,实例化枚举对象,你在枚举类中定义了多少个就会实例化多少个,JVM为了保证每一个枚举类元素的唯一实例,是不会允许外部进行new的,所以会把构造函数设计成private,防止用户生成实例,破坏唯一性。

三、枚举类添加属性和构造器

枚举类内也可以定义属性和方法,可是是静态的和非静态的。但是,构造器一定是私有的,前面已经说过了,枚举类型被设计成了单例模式。构造器需定义成私有的,这样就不能在别处申明此类的对象了。它的Field不应该被改变,这样会更安全,而且代码更加简洁。所以我们将Field用private final修饰

实际上在第一行写枚举类实例的时候,默认是调用了构造器,所以此处需要传入参数,因为没有显式申明无参构造器,只能调用有参数的构造器。

public enum SeasonEnum {
    SPRING("1","春天"),SUMMER("2","夏天"),FALL("3","秋天"),WINTER("4","冬天");
    
    private final int code;

    private final String name;

    private SeasonEnum(int code,String name)
    {
        this.code= code;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String getCode() {
        return code;
    }
}

四、枚举类实现接口

枚举类可以实现一个或多个接口。与普通类一样,实现接口的时候需要实现接口中定义的所有方法,若没有完全实现,那这个枚举类就是抽象的,只是不需显式加上abstract修饰,系统化会默认加上。

public enum Operation {
    PLUS{
        @Override
        public double eval(double x, double y) {
            return x + y;
        }
        
    },
    MINUS{
        @Override
        public double eval(double x, double y) {
            return x - y;
        }
        
    },
    TIMES{
        @Override
        public double eval(double x, double y) {
            return x * y;
        }
        
    },
    DIVIDE{
        @Override
        public double eval(double x, double y) {
            return x / y;
        }
        
    };
    
    /**
     * 抽象方法,由不同的枚举值提供不同的实现。
     * @param x
     * @param y
     * @return
     */
    public abstract double eval(double x, double y);
}

五、其他API

1. 返回指定名称和指定类的某个枚举类

static Enum valueOf(Class enumClass, String name)

2.返回枚举常量名

String toString()

3.返回枚举常量的序数 

int ordinal() 

4.返回枚举的所有值

static T[] values()

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值