《effective java》之五:枚举和注解
第30条:用enum代替int常量:
public enum Operation {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;Operation(String symbol) {this.symbol = symbol;}@Overridepublic String toString() {return symbol;}abstract double apply(double x, double y);// Implementing a fromString method on an enum type - Page 154private static final Map<String, Operation> stringToEnum = new HashMap<String, Operation>();static { // Initialize map from constant name to enum constantfor (Operation op : values())stringToEnum.put(op.toString(), op);}// Returns Operation for string, or null if string is invalidpublic static Operation fromString(String symbol) {return stringToEnum.get(symbol);}// Test program to perform all operations on given operandspublic static void main(String[] args) {double x = Double.parseDouble(args[0]);double y = Double.parseDouble(args[1]);for (Operation op : Operation.values())System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));}}
?
第31条:用实例域代替序数:
public enum Ensemble {SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9), DECTET(10), TRIPLE_QUARTET(12);private final int numberOfMusicians;Ensemble(int size) {this.numberOfMusicians = size;}public int numberOfMusicians() {return numberOfMusicians;}}
?
?第32条:用EnumSet代替位域:
public class Text {public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}// Any Set could be passed in, but EnumSet is clearly bestpublic void applyStyles(Set<Style> styles) {// Body goes here}// Sample usepublic static void main(String[] args) {Text text = new Text();text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC)); }}
?
第33条:用EnumMap代替序数索引:
public enum Phase {SOLID, LIQUID, GAS;public enum Transition {MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);private final Phase src;private final Phase dst;Transition(Phase src, Phase dst) {this.src = src;this.dst = dst;}// Initialize the phase transition mapprivate static final Map<Phase, Map<Phase, Transition>> m = new EnumMap<Phase, Map<Phase, Transition>>(Phase.class);static {for (Phase p : Phase.values())m.put(p, new EnumMap<Phase, Transition>(Phase.class));for (Transition trans : Transition.values())m.get(trans.src).put(trans.dst, trans);}public static Transition from(Phase src, Phase dst) {return m.get(src).get(dst);}}// Simple demo program - prints a sloppy tablepublic static void main(String[] args) {for (Phase src : Phase.values())for (Phase dst : Phase.values())if (src != dst)System.out.printf("%s to %s : %s %n", src, dst,Transition.from(src, dst));}}
?
第34条:用接口模拟可伸缩的枚举:
public interface Operation {double apply(double x, double y);}
?
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;}},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;BasicOperation(String symbol) {this.symbol = symbol;}@Overridepublic String toString() {return symbol;}}
?
第35条:注解优于命名模式:
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface ExceptionTest {Class<? extends Exception>[] value();}public class Sample2 {@ExceptionTest(ArithmeticException.class)public static void m1() { // Test should passint i = 0;i = i / i;}@ExceptionTest(ArithmeticException.class)public static void m2() { // Should fail (wrong exception)int[] a = new int[0];int i = a[1];}@ExceptionTest(ArithmeticException.class)public static void m3() {} // Should fail (no exception)// Code containing an annotation with an array parameter - Page 174@ExceptionTest({ IndexOutOfBoundsException.class,NullPointerException.class })public static void doublyBad() {List<String> list = new ArrayList<String>();// The spec permits this method to throw either// IndexOutOfBoundsException or NullPointerExceptionlist.addAll(5, null);}}
?
public class RunTests {public static void main(String[] args) throws Exception {int tests = 0;int passed = 0;Class testClass = Class.forName(args[0]);for (Method m : testClass.getDeclaredMethods()) {if (m.isAnnotationPresent(Test.class)) {tests++;try {m.invoke(null);passed++;} catch (InvocationTargetException wrappedExc) {Throwable exc = wrappedExc.getCause();System.out.println(m + " failed: " + exc);} catch (Exception exc) {System.out.println("INVALID @Test: " + m);}}// Array ExceptionTest processing code - Page 174if (m.isAnnotationPresent(ExceptionTest.class)) {tests++;try {m.invoke(null);System.out.printf("Test %s failed: no exception%n", m);} catch (Throwable wrappedExc) {Throwable exc = wrappedExc.getCause();Class<? extends Exception>[] excTypes = m.getAnnotation(ExceptionTest.class).value();int oldPassed = passed;for (Class<? extends Exception> excType : excTypes) {if (excType.isInstance(exc)) {passed++;break;}}if (passed == oldPassed)System.out.printf("Test %s failed: %s %n", m, exc);}}}System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);}}
?
第36条:坚持使用Override注解:
?
第37条:用标记接口定义类型:
?