我们存放一些静态变量,像是一些变量和设置,等等等等,我们尽量使用ENUM,因为ENUM是不可实例化和继承的,所以他很安全,它是在程序一开始运行的时候进行一些编译,修改ENUM不需要再次编译。

在什么时候用ENUM呢。摘录如下。

Use enums when you want to define a range of values that something can be. Colour is an obvious example like:

public enum Colour
{
White,
Red,
Blue
}
Or maybe a set of possible things like: (Example I stole from here as I'm lazy) [FlagsAttribute]
enum DistributedChannel
{
None = 0,
Transacted = 1,
Queued = 2,
Encrypted = 4,
Persisted = 16,
FaultTolerant = Transacted | Queued | Persisted
}
Constants should be for a single value, like PI. There isn't a range of PI values, there is just PI.

一个简单应用

public enum CircleArea {
CIRCLEONE(1.2),
CIRCLETWO(2.5),
CIRCLETHREE(3.5); private final double r; private static final double PI=3.14; CircleArea(double r) {
this.r=r;
} public double R(){
return r;
} public double Area(){
return r*r*PI;
} public double SomeArea(int Some){
return Some*r*r*PI;
}
} 测试

for (CircleArea c:CircleArea.values() ){

System.out.println(c+" "+c.R()+" "+c.SomeArea(3)+"");
}

 

使用ENUM的时候,如果enum里面有ABstract ,则声明的时候也必须要有,所以以下尽量使用Operation2的形式。

public enum Operation {
PLUS, MINUS, TIMES, DIVDE;
double apply(double x, double y) {
switch (this) {
case PLUS:
return x + y;
case MINUS:
return x - y;
case TIMES:
return x * y;
case DIVDE:
return x / y;
}
throw new AssertionError("未定义类型" + this);
}
}
public enum Operation2 {
PLUS {
double apply(double x, double y) {
return x + y;
}
},
MINUS {
double apply(double x, double y) {
return x - y;
}
},
TIMES {
double apply(double x, double y) {
return x * y;
}
},
DIVIDE {
double apply(double x, double y) {
return x / y;
}
}; abstract double apply(double x, double y);
} /////////////////////////带符号输出的
public enum Operation3 {
PLUS("+") {
double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
double apply(double x, double y) {
return x / y;
}
}; private final String symbol; Operation3(String symbol) {
this.symbol = symbol;
}
@Override public String toString(){
return symbol;
} abstract double apply(double x, double y);
}

除了EnumSet和EnumMap,都不要使用ordinals。

public enum WrongIdEnum {
FIRST,SECOND,THIRD;
public int getId(){
return ordinal()+1;
}
} public enum IdEnum {
FIRST(1),SECOND(2),THIRD(3); private final int id;
IdEnum(int id){
this.id=id;
}
public int getId(){
return id;
}
}

上面两个Enum都可以实现返回ID的功能,但是千万不要使用第一个类型,因为第一个类型非常不方便增删,如果我在中间删掉一个定量,因为ordinals代表的是当前在Enum的排序第几个,后面所代表的意义全部会乱。

在JAVA中,尽量不要使用位操作定量,可以使用EnumSet来替换,EnumSet比较安全且高效,继承了Enum的所有优点,什么是位操作定量,需要了解一下。附上EnumSet的一个实现。

public enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY;
} public class Worker {
private String name;
private Set<Day> avalibleDay;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Day> getAvalibleDay() {
return avalibleDay;
}
public void setAvalibleDay(Set<Day> avalibleDay) {
this.avalibleDay = avalibleDay;
}
public Worker(String name, Set<Day> avalibleDay) {
super();
this.name = name;
this.avalibleDay = avalibleDay;
}
} public static void getNoDay(Worker[] work){//哪天都没人来
Set<Day> days = EnumSet.allOf(Day.class);
for(Worker w:work){
days.removeAll(w.getAvalibleDay());//在这里体现“位”操作
}
System.out.println("都没人在的是"+days);
} public static void getEveryDay(Worker[] work){//哪天都来人
Set<Day> days = EnumSet.allOf(Day.class);
for(Worker w:work){
days.retainAll(w.getAvalibleDay());//在这里体现“位”操作
}
System.out.println("都有人在的是"+days);
} Worker[] workers = new Worker[]{
new Worker("张三", EnumSet.of(
Day.TUESDAY, Day.WEDNESDAY, Day.FRIDAY)),
new Worker("李四", EnumSet.of(
Day.TUESDAY, Day.THURSDAY, Day.SATURDAY)),
new Worker("王五", EnumSet.of(
Day.TUESDAY, Day.THURSDAY)),
};
MyTestMethod.getNoDay(workers);
MyTestMethod.getEveryDay(workers); //输出
//都没人在的是[MONDAY, SUNDAY]
//都有人在的是[TUESDAY]

 

用接口模拟可扩展Enum

设计枚举的时候最好不要设计可扩展性,如果实在要设计,可以使用接口的方式实现。

public interface OperationInterface {
double apply(double x,double y);
} public enum OperationEnum implements OperationInterface {//可以设计很多个implements OperationInterface的枚举,实现枚举的变相扩展
PLUS("+") {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
@Override
public double apply(double x, double y) {
return x - y;
}
};
private final String symbol; OperationEnum(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
/**
* @Description:
* @author: shengzhizhi
* @modifier:
* @date: 2018年8月20日 下午5:58:21
*/
return this.symbol;
} } public class TestEnumForImplement { public static void main(String[] args) {
double d1 = 1.2;
double d2 = 2.2;
say(Arrays.asList(OperationEnum.values()),d1,d2);
} public static void say(Collection<? extends OperationInterface> opSet, double x, double y) {
for (OperationInterface e : opSet) {
System.out.printf("the methos is %s, result is %f%n", e, e.apply(x, y));
}
}
}

Effective Java (ENUM篇)的更多相关文章

  1. [Effective Java] 创建和销毁对象篇

    [Effective Java] 创建和销毁对象篇 1. 优先考虑用静态工厂方法代替构造器 优点: - 静态工厂方法相比于构造器,它们有名称 - 不需要每次在使用的时候创建一个对象 - 可以返回原返回 ...

  2. Effective Java 第二版 Enum

    /** * Effective Java 第二版 * 第30条:用enum代替int常量 */ import java.util.HashMap;import java.util.Map; publi ...

  3. Effective Java通俗理解(持续更新)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  4. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  5. effective java笔记之单例模式与序列化

    单例模式:"一个类有且仅有一个实例,并且自行实例化向整个系统提供." 单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法 ...

  6. Effective Java通俗理解(上)

    这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...

  7. 《Effective Java》读书笔记(一)之创建和销毁对象

    最近在研读<Effective Java>一书,读书不做点笔记,感觉很容易就忘掉,于是用本篇博客来记录阅读此书的笔记. 郑重声明: 由于是<Effective Java>一书的 ...

  8. 如何创建和销毁对象(Effective Java 第二章)

    最近有在看Effective Java,特此记录下自己所体会到的东西,写篇博文会更加的加深印象,如有理解有误的地方,希望不吝赐教. 这章主题主要是介绍:何时以及如何创建对象,何时以及如何避免创建对象, ...

  9. 简单认识java enum枚举

    什么是枚举 枚举是java5中新增的特性,他是一个特殊的数据类型,他的特殊性在于他既是一种类类型,又比类类型多了安全性,简洁性,便捷性.java枚举类型是功能十分强大齐全的类,功能比其他语言中的对等物 ...

  10. Effective Java —— 用私有构造器或枚举类型强化单例属性

    本文参考 本篇文章参考自<Effective Java>第三版第三条"Enforce the singleton property with a private construc ...

随机推荐

  1. linux中ping IP可以通但是主机名不通

    在/etc/hosts中配置要ping的主机名称映射 例如: ping test1不通 在/etc/hosts中配置 ip地址  test1

  2. 最长上升子序列 nlogn

    ; LL num[N]; LL dp[N]; LL go(LL l, LL r, LL k) { for (; r >= l; r--) if (dp[r] <= k) return r; ...

  3. 图解GIT,ZT

    图解GIT,ZT http://nettedfish.sinaapp.com/blog/2013/08/05/deep-into-git-with-diagrams/

  4. Date类型与String类型的相关问题

    今天完成boss交代的任务时,遇到Date类型与String类型的相关问题,参考了网上的一些例子,并且自己写了demo,现在记录下了总结一下: (一)判断一个字符串是不是合法的日期格式 public ...

  5. spring boot 2.0(一)权威发布spring boot2.0

    Spring Boot2.0.0.RELEASE正式发布,在发布Spring Boot2.0的时候还出现一个小插曲,将Spring Boot2.0同步到Maven仓库的时候出现了错误,然后Spring ...

  6. C++的成员初始化列表和构造函数体(以前未知)

    成员的初始化列表和构造函数在对成员指定初值方面是不一样的.成员初始化列表是对成员初始化,而构造函数,是对成员赋值 成员初始化列表使用初始化的方式来为数据成员指定初值, 而构造函数的函数体是通过赋值的方 ...

  7. springboot 定时任务部署至linux服务器上后会执行两次问题

    springboot定时任务在本地运行时,正常执行且只执行一次,但是在maven打包成war包,部署至linux服务器上之后,定时任务奇怪的执行了两次. 由于未做负载均衡,所以可以先排除是因为多台服务 ...

  8. django学习之——模版

    为了减少模板加载调用过程及模板本身的冗余代码,Django 提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板, 要使用此模板加载API,首先你必须将模板的保存位置告诉框架. 设置的保存文 ...

  9. Windows下定时任务

    windows计划任务 1.写一个PHP程序,命名为test.php,内容如下所示: <? $fp = fopen("test.txt", "a+"); ...

  10. 套接字编程,建立连接connect,绑定套接字bind

    1.建立连接 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数sockfd是由函数socket创建 ...