Effective Java (ENUM篇)
我们存放一些静态变量,像是一些变量和设置,等等等等,我们尽量使用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篇)的更多相关文章
- [Effective Java] 创建和销毁对象篇
[Effective Java] 创建和销毁对象篇 1. 优先考虑用静态工厂方法代替构造器 优点: - 静态工厂方法相比于构造器,它们有名称 - 不需要每次在使用的时候创建一个对象 - 可以返回原返回 ...
- Effective Java 第二版 Enum
/** * Effective Java 第二版 * 第30条:用enum代替int常量 */ import java.util.HashMap;import java.util.Map; publi ...
- Effective Java通俗理解(持续更新)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
- effective java笔记之单例模式与序列化
单例模式:"一个类有且仅有一个实例,并且自行实例化向整个系统提供." 单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法 ...
- Effective Java通俗理解(上)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- 《Effective Java》读书笔记(一)之创建和销毁对象
最近在研读<Effective Java>一书,读书不做点笔记,感觉很容易就忘掉,于是用本篇博客来记录阅读此书的笔记. 郑重声明: 由于是<Effective Java>一书的 ...
- 如何创建和销毁对象(Effective Java 第二章)
最近有在看Effective Java,特此记录下自己所体会到的东西,写篇博文会更加的加深印象,如有理解有误的地方,希望不吝赐教. 这章主题主要是介绍:何时以及如何创建对象,何时以及如何避免创建对象, ...
- 简单认识java enum枚举
什么是枚举 枚举是java5中新增的特性,他是一个特殊的数据类型,他的特殊性在于他既是一种类类型,又比类类型多了安全性,简洁性,便捷性.java枚举类型是功能十分强大齐全的类,功能比其他语言中的对等物 ...
- Effective Java —— 用私有构造器或枚举类型强化单例属性
本文参考 本篇文章参考自<Effective Java>第三版第三条"Enforce the singleton property with a private construc ...
随机推荐
- lanmp环境中创建个软连接
进入default,创建关于框架的链接 然后编辑配置文件 这样就可以在线上访问了.
- get post 小结
get参数通过url传递,post放在request body中. get请求在url中传递的参数是有长度限制的,而post没有. get比post更不安全,因为参数直接暴露在url中,所以不能用来传 ...
- Spring Boot常用注解
SpringBoot注解大全 一.注解(annotations)列表 @SpringBootApplication:包含了@ComponentScan.@Configuration和@Enable ...
- Oracle中事务处理控制用法
oracle 事物控制包括 COMMINT ROLLBACK SAVEPOINT avepoint是事务内部允许部分rollback的标志符.因为事务中对记录做了修改,我们可以在事务中创建savepo ...
- docker实战系列之快速删除docker中的容器
1.停用全部运行中的容器 docker stop $(docker ps -q) 2.删除全部容器 docker rm $(docker ps -aq) 3.停用并删除容器 docker stop $ ...
- Const的使用
const意味为readonly,即只读,const可被施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体 使用: const修饰变量时本质是 const在谁后面谁就不可修改,const在 ...
- qt 调用zlib压缩与解压缩功能
Zlib是一种免费且通用的压缩库,由于Zlib压缩效果比LZW好,而且解压缩速度快,更重要的是商业软件中使用Zlib不需要缴纳版权费,所以很多游戏都使用Zlib压缩资源文件. Zlib是由Jean-l ...
- 微信小程序: rpx与px,rem相互转换
官方上规定屏幕宽度为20rem,规定屏幕宽为750rpx,则1rem=750/20rpx. 微信官方建议视觉稿以iPhone 6为标准:在 iPhone6 上,屏幕宽度为375px,共有750个物理像 ...
- 【转】Windows守护进程的一种简单实现
一讲到守护进程,很多人都想到了Linux系统,确实在Windows上这个说的比较少.今天上午群里有个朋友问我了下Windows下守护进程的实现问题,我想了想,简单用C++写了个小例子,用来实现系统开机 ...
- matlab画图变粗脚本
http://blog.sina.com.cn/s/blog_708637950100uag0.html figure_FontSize=18;set(get(gca,'XLabel'),'FontS ...