Effective Java 30 Use Enums instead of int constants
Enumerated type is a type whose legal values consist of a fixed set of constants, such as the seasons of the year.
// The int enum pattern - severely deficient!
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;
The basic idea behind Java's enum types is simple: they are classes that export one instance for each enumeration constant via a public static final field.
To associate data with enum constants, declare instance fields and write a constructor that takes the data and stores it in the fields.
Note
- unless you have a compelling reason to expose an enum method to its clients, declare it private or, if need be, package-private (Item 13).
- If an enum is generally useful, it should be a top-level class; if its use is tied to
a specific top-level class, it should be a member class of that top-level class (Item22)
- Compiler will reminds you that abstract methods in an enum type must be overridden with concrete methods in all of its constants.
/**
* Demo for enum type use abstract methods for Compile time checking on added enum type.
*/
package com.effectivejava.EnumAnnotations;
import java.util.HashMap;
import java.util.Map;
/**
* @author Kaibo
*
*/
public enum Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
public abstract double apply(double x, double y);
}
Note
Enum types have an automatically generated valueOf(String)method that translates a constant's name into the constant itself. If you override the toString method in an enum type, consider writing a fromString method to translate the custom string representation back to the corresponding enum.
// Implementing a fromString method on an enum type
private static final Map<String, Operation> stringToEnum = new HashMap<String, Operation>();
static { // Initialize map from constant name to enum constant
for (Operation op : values())
stringToEnum.put(op.toString(), op);
}
// Returns Operation for string, or null if string is invalid
public static Operation fromString(String symbol) {
return stringToEnum.get(symbol);
}
4. Use nested enum for the strategy enum pattern. Using constant-specific methods.
/**
* Demo for the "Using Nested enum for enum strategy pattern."
*/
package com.effectivejava.EnumAnnotations;
/**
* @author Kaibo
*
*/
// The strategy enum pattern
enum PayrollDay {
MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(
PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(
PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
private final PayType payType;
PayrollDay(PayType payType) {
this.payType = payType;
}
double pay(double hoursWorked, double payRate) {
return payType.pay(hoursWorked, payRate);
}
// The strategy enum type
private enum PayType {
// constant-specific methods
WEEKDAY {
double overtimePay(double hours, double payRate) {
return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT)
* payRate / 2;
}
},
WEEKEND {
double overtimePay(double hours, double payRate) {
return hours * payRate / 2;
}
};
private static final int HOURS_PER_SHIFT = 8;
abstract double overtimePay(double hrs, double payRate);
double pay(double hoursWorked, double payRate) {
double basePay = hoursWorked * payRate;
return basePay + overtimePay(hoursWorked, payRate);
}
}
}
5. Switches on enums are good for augmenting external enum types with constant-specific behavior.
// Switch on an enum to simulate a missing method
public static Operation inverse(Operation op) {
switch(op) {
case PLUS: return Operation.MINUS;
case MINUS: return Operation.PLUS;
case TIMES: return Operation.DIVIDE;
case DIVIDE: return Operation.TIMES;
default: throw new AssertionError("Unknown op: " + op);
}
}
Summary
Enums are far more readable, safer, and more powerful than int constants. Enums can benefit from associating data with each constant sand providing methods whose behavior is affected by this data. When enums benefit from assocating multiple behaviors with a single method perfer constant-specific methods to enums that switch on their own values. Consider the strategy enum pattern if multiple enum constants share common behaviors.
Effective Java 30 Use Enums instead of int constants的更多相关文章
- effective java——30使用enum
1, 枚举太阳系八大行星 package com.enum30.www; public enum Planet {//枚举太阳系八大行星 MERCURY(3.302e+23,2.439e6), VEN ...
- Effective Java Index
Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...
- 《Effective Java》读书笔记 - 6.枚举和注解
Chapter 6 Enums and Annotations Item 30: Use enums instead of int constants Enum类型无非也是个普通的class,所以你可 ...
- Effective Java 第三版——30. 优先使用泛型方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java之避免创建不必要的对象
Effective Java中有很多值得注意的技巧,今天我刚开始看这本书,看到这一章的时候,我发现自己以前并没有理解什么是不必要的对象,所以拿出来跟大家探讨一下,避免以后犯不必要的错误! 首先书中对不 ...
- [Effective Java]第八章 通用程序设计
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 对于所有对象都通用方法的解读(Effective Java 第二章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- Effective Java通俗理解(持续更新)
这篇博客是Java经典书籍<Effective Java(第二版)>的读书笔记,此书共有78条关于编写高质量Java代码的建议,我会试着逐一对其进行更为通俗易懂地讲解,故此篇博客的更新大约 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
随机推荐
- [linux]scp指令
实例1:从远处复制文件到本地目录 $scp root@10.6.159.147:/opt/soft/demo.tar /opt/soft/ 说明: 从10.6.159.147机器上的/opt/soft ...
- FUNCS.H中的函数声明
/*************************************************************************** ...
- SQL Server 2012:SQL Server体系结构——一个查询的生命周期(第3部分)(完结)
一个简单的更新查询 现在应该知道只读取数据的查询生命周期,下一步来认定当你需要更新数据时会发生什么.这个部分通过看一个简单的UPDATE查询,修改刚才例子里读取的数据,来回答. 庆幸的是,直到存取方法 ...
- 谈HTTP的KeepAlive
为什么要使用KeepAlive? 终极的原因就是需要加快客户端和服务端的访问请求速度.KeepAlive就是浏览器和服务端之间保持长连接,这个连接是可以复用的.当客户端发送一次请求,收到相应以后,第二 ...
- MyBatis魔法堂:ResultMap详解
一.前言 MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库遵循第三范式或BCNF,但实际事与愿违,那么结果集映射就是MyBatis为我们提供这种理想与现实间转换的手段了, ...
- 指定winfrom程序配置文件
System.AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\ABC.CONFIG"); 但是当 ...
- linq之let子句
在Linq查询中Let子句可以创建一个新的范围变量,并使用该变量保存表达式的结果. 看下面的例子: private void LetQuery() { List<UserBaseInfo> ...
- 译:什么是ViewData的, ViewBag和TempData? - MVC为当前和后续请求之间传递数据的三种方法
译文出处:http://www.codeproject.com/Articles/476967/WhatplusisplusViewData-cplusViewBagplusandplusTem AS ...
- [转]微信公众平台WeChat PHP SDK
地址:https://github.com/dodgepudding/wechat-php-sdk 微信公众平台php开发包,细化各项接口操作,支持链式调用 微信支付接入文档: https://mp. ...
- Delphi的几个跨平台小游戏例子。
Embarcadero开源了几个FireMonkey的小游戏,支持Windows, Android,Ios, MacOS等. 源码地址: https://github.com/EmbarcaderoP ...