用enum代替it常量
-
如果一个枚举具有普遍适用性。应该成为一个顶层类,如果只被用在一个特定顶层类,就应该是该顶层类的一个成员类
-
为了将数据和枚举常量关联起来,得声明实例域,并编写一个带有数据并将数据保存在域中的构造器
package codeTemplate.effectiveJava.bean; public enum Colors { YELLOW(124), RED(123); private final int num; Colors(int num) { this.num = num; } }
-
将不同的行为与每个枚举常量结合(一个抽象方法,分别实现)
package codeTemplate.effectiveJava.bean; public enum Colors { YELLOW(255){public int apply(int x){return x+255;}}, RED(123){public int apply(int x){return x+123;}}; private int num; Colors(int num) { this.num = num; } public abstract int apply(int x); }
-
如果多个但不是所有枚举常量同时共享相同的行为,则使用策略枚举
package codeTemplate.effectiveJava.bean; public enum Colors { YELLOW(PrintType.ONE), RED(PrintType.ONE), BLUE(PrintType.TWO); private PrintType printType; Colors(PrintType printType) { this.printType = printType; } void print() { printType.print(); } private enum PrintType{ ONE{ void print(){ System.out.println(1); };}, TWO{void print(){ System.out.println(2); };}; abstract void print(); } public static void main(String[] args) { Colors.RED.print(); } }
用实例域代替序数
所有的枚举都有一个ordinal方法,它返回每个枚举常量在类型中的数学位置
package codeTemplate.effectiveJava.bean;
public enum Color {
RED(1),GREEN(2),BLUE(3);
public int numberOfColor() {
return ordinal();
}
}
永远不要根据枚举的序数导出与它相关联的值,而是要将它保存在一个实例域中
package codeTemplate.effectiveJava.bean;
public enum Color {
RED(1),GREEN(2),BLUE(3);
private int num;
Color(int num) {
this.num = num;
}
public int number() {
return num;
}
}
用EnumSet代替位域
位域:用OR位运算将几个常量合并到一个集合中,如:
int RED1 = 1;
int GREEN1 = 2;
System.out.println(RED1 | GREEN1);
package codeTemplate.effectiveJava.bean;
public enum Color {
RED(1),GREEN(2),BLUE(3);
private int num;
Color(int num) {
this.num = num;
}
public int number() {
return num;
}
}
用EnumMap代替序数索引
多维就是EnumMap<...EnumMap<...>>
一般情况都不使用Enum.ordinal方法
用接口模拟可扩展的模式
虽然无法编写可扩展的枚举类型,但是可以通过编写接口以及实现该接口的基础枚举类型来对它进行模拟
package codeTemplate.effectiveJava.pojo;
public interface Operation {
double apply(double x, double y);
}
package codeTemplate.effectiveJava.pojo;
public enum BasicOperation implements Operation{
PLUS("+"){
public double apply(double x, double y) {
return x+y;
}
},
MINUS("-"){
public double apply(double x, double y) {
return x-y;
}
};
private final String symbol;
BasicOperation(String symbol) {
this.symbol = symbol;
}
}
package codeTemplate.effectiveJava.pojo;
public enum ExtendedOperation implements Operation{
PLUS("*"){
public double apply(double x, double y) {
return x*y;
}
},
MINUS("/"){
public double apply(double x, double y) {
return x/y;
}
};
private final String symbol;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
}
注解优先于命名模式
命令模式:如测试方法:testXXXXX,以test开头,
注释@Test
使用Method.invoke反射式地运行类中所有标注了某个注解的类
定义一个注解
package codeTemplate.effectiveJava.pojo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
}
使用和执行(利用反射)
package codeTemplate.effectiveJava.pojo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestPojo {
@Test
public void common() {
System.out.println("123");
}
public void testX() {
System.out.println(234);
}
public static void main(String[] args) throws ClassNotFoundException {
int num = 0;
int pass = 0;
for (Method method : Class.forName("codeTemplate.effectiveJava.pojo.TestPojo").getDeclaredMethods()) {
System.out.println(method.getName());
if (method.isAnnotationPresent(Test.class)) {
num++;
try {
method.invoke(new TestPojo());
pass++;
} catch (InvocationTargetException | IllegalAccessException e) {
System.out.println(e);
}
}
}
System.out.println("num is " + num + " pass is " + pass);
}
}
坚持使用Override注解
用标记接口定义类型
标记接口:不包含方法声明的接口,它只是指明(或标2明)一个类实现了具有某种属性的接口
标记注解@XX
如:Serializable(表示实例可以序列化)
package java.io;
public interface Serializable {
}
若标记是应用于任何程序元素而不是类或者接口,就必须使用注解