枚举
什么时候需要使用枚举?
当程序中需要使用到一组常量(整型,字符串)时,就应该使用枚举对这些常量进行封装。
如,星期一到星期天、性别分男和女等
使用枚举可以带来哪些好处:
类型安全,防止传入错误的参数值
可读性好,比int值强
不易出错,比硬编码字符串到程序各个角落好
枚举实例可以具备行为,操作起来更加方便
使用枚举替换int常量和字符串常量
public enum Sex { MALE, FEMALE; }
用实例域替代枚举自身的序数
如果需要使用枚举常量的序数,最好自己定义,不要使用默认的ordinal实现
public enum Priority { STEP_A(0, "洗脸"), STEP_B(1, "刷牙"), STEP_C(2, "抽烟"), STEP_D(2, "WC"), STEP_E(3, "上班"); private int ordinal; private String task; Priority(int ordinal, String task) { this.ordinal = ordinal; this.task = task; } public int getOridnal() { return this.ordinal; } @Override public String toString() { return this.ordinal + ": " + this.task; } } //test public static void main(String[] args) { for(Priority p : Priority.values()) { System.out.println(p); } }
EnumSet
通过集合接收几个枚举常量
package effective.chapter6; import java.util.EnumSet; public class Text { public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH; } public static void applyStyle(EnumSet<? extends Style> styles) { for(Style s : styles) { System.out.println("apply style: " + s); } } //test public static void main(String[] args) { Text.applyStyle(EnumSet.of(Style.BOLD, Style.STRIKETHROUGH)); } }
EnumMap
枚举类型作为Map的key进行使用
描述两个阶段映射到一个阶段过渡
package effective.chapter6; import java.util.EnumMap; import java.util.Map; /** * 嵌套枚举定义 */ public enum Phase { SOLID("固体"), LIQUID("液体"), GAS("汽体"); private String status; Phase(String status) { this.status = status; } @Override public String toString() { return status; } //不同阶段转换的过程 public enum Transition { MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS); private Phase src; private Phase dst; Transition(Phase src, Phase dst) { this.src = src; this.dst = dst; } //key: 起始状态 //value: [key:结束状态,value:转变过程] private 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); } @Override public String toString() { return this.src + "->" + this.dst; } } }
public class TestNestEnum { public static void main(String[] args) { Transition trans = Phase.Transition.from(Phase.SOLID, Phase.LIQUID); System.out.println(trans); } }
结果:固体->液体
通过接口扩展枚举的功能
public interface Operation { double aplly(double x, double y); }
public enum BasicOperation implements Operation { PLUS("+"){ @Override public double aplly(double x, double y) { return x + y; } }, MINUS("-"){ @Override public double aplly(double x, double y) { return x - y; } }, TIMES("*"){ @Override public double aplly(double x, double y) { return x * y; } }, DIVIDE("/"){ @Override public double aplly(double x, double y) { return x / y; } }, EXP("^") { @Override public double aplly(double x, double y) { return Math.pow(x, y); } }, REMAINDER("%"){ @Override public double aplly(double x, double y) { return x % y; } }; private final String symbol; BasicOperation(String symbol) { this.symbol = symbol; } @Override public String toString(){ return symbol; } @Override public double aplly(double x, double y) { throw new RuntimeException("You must implements method in each enum instance!"); } }
class TestEnumInterface { public static void main(String[] args) { double x = 2.17; double y = 3.02; //数组转换为集合 testEnum(Arrays.asList(BasicOperation.values()), x, y); } //泛型参数接收枚举集合 public static void testEnum(Collection<? extends Operation> opSet, double x, double y) { for(Operation op : opSet) System.out.printf("%f %s %f = %f%n", x, op, y, op.aplly(x, y)); } }
结果:
2.170000 + 3.020000 = 5.190000
2.170000 - 3.020000 = -0.850000
2.170000 * 3.020000 = 6.553400
2.170000 / 3.020000 = 0.718543
2.170000 ^ 3.020000 = 10.377874
2.170000 % 3.020000 = 2.170000
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
注解
标记注解
package effective.chapter6; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)//配置‘@AnnoTest’应该被保留到运行阶段,在运行阶段通过反射定位此注解 @Target(ElementType.METHOD)//配置‘@AnnoTest’可使用的目标:用在方法上,而不是用在字段或者类上 public @interface MyAnno { }
package effective.chapter6; /** * 将注解标注到方法上 */ public class Sample { @MyAnno public static void m1() {} public static void m2() {} @MyAnno public static void m3() { throw new RuntimeException("Boommmm"); } public static void m4() {} @MyAnno public void m5() {} public void m6() {} @MyAnno public static void m7() { throw new RuntimeException("Boommmm again"); } public static void m8(){} }
package effective.chapter6; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 读取注解,只处理那些标记了特定注解的方法 * 在Sample类中使用@MyAnno注解对若干方法进行标记 * 1.反射Sample类中的方法 * 2.判断方法是否被@MyAnno标记了 * 3.如果标记了,则以静态方法反射调用此方法 * 4.统计被正确调用的静态方法个数,与出现异常的方法个数 * 5.未标记@MyAnno注解的方法不会得到执行 */ public class Test { public static void main(String[] args) throws Exception { int tests = 0; int passed = 0; Class<?> testClass = Class.forName("effective.chapter6.Sample"); for(Method m : testClass.getDeclaredMethods()) { //判断方法上的注解是否为@MyAnno if(m.isAnnotationPresent(MyAnno.class)) { tests++; try{ //反射调用静态方法 m.invoke(null); passed++; } catch (InvocationTargetException wrappedExc) { Throwable exc = wrappedExc.getCause(); System.out.println(m + "failed:" + exc); } catch (Exception e) { System.out.println("Invalid @MyAnno:" + m); } } } System.out.printf("passed: %d, failed %d%n", passed, tests - passed); } }
注解中定义数组参数
package effective.chapter6; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //配置‘@AnnoTest’应该被保留到运行阶段,在运行阶段通过反射定位此注解 @Retention(RetentionPolicy.RUNTIME) //配置‘@AnnoTest’可使用的目标:用在方法上,而不是用在字段或者类上 @Target(ElementType.METHOD) public @interface MyAnno { Class<? extends Exception>[] values();//接收一组异常类 }
package effective.chapter6; import java.util.ArrayList; import java.util.List; /** * 将注解标注到方法上 * 给注解的数组参数添加配置 */ public class Sample { @MyAnno(values = {IndexOutOfBoundsException.class, NullPointerException.class}) public static void badMethod() { List<String> list = new ArrayList<String>(); list.addAll(5,null); } }
package effective.chapter6; import java.lang.reflect.Method; /** * 对抛出特定异常的方法进行测试 */ public class Test { public static void main(String[] args) throws Exception { int tests = 0; int passed = 0; Class<?> testClass = Class.forName("effective.chapter6.Sample"); for(Method m : testClass.getDeclaredMethods()) { //判断方法上的注解是否为@MyAnno if(m.isAnnotationPresent(MyAnno.class)) { tests++; try{ //反射调用静态方法 m.invoke(null); System.out.printf("Tests %s failed: no exception%n", m); } catch (Throwable wrappedExc) { Throwable excCause = wrappedExc.getCause(); Class<? extends Exception>[] excTypes = m.getAnnotation(MyAnno.class).values(); int oldPassed = passed; for(Class<? extends Exception> excType : excTypes) { if(excType.isInstance(excCause)) { passed++; break; } } if(passed == oldPassed) System.out.printf("Test %s failed: %s %n", m, excCause); else System.out.println("Test ok!"); } } } System.out.printf("passed: %d, failed %d%n", passed, tests - passed); } }
建议:坚持使用@overrider注解,避免非法错误!
相关推荐
作者简介 作者:(美国)迈耶斯(Scott Meyers) 迈耶斯(Scott Meyers),二十多年来,Scott Meyers的Effective C++系列书籍(包括《Effective C++》《More Effective C++》和《Effective STL》)为C++编程语言...
Effective-Java:Effective Java的所有练习程序
《Effective Java》第三版中文版目录 第一章 介绍 1 第二章 创建和销毁对象 4 1 考虑用静态工厂方法替换构造器 4 2 当遇到多个构造器参
java项目经验源码 Effective Java 作者: 实践《Effective Java》书中的经验法则示例代码,结合Java源码来理解这些最佳实践,并应用于实际项目。 Effective Java, Third Edition Updated for Java 9, Best practices...
Effective Java读书笔记.pdf
effective-java.pdf
Effective java 3 学习记录
Effective-Java Effective Java中文版第二版示例代码
java源码测试 effective-java 读Effective Java(中文版第3版)阅读源码测试案列
effective java 读书笔记,第二版自己摘要并翻译,以备速查。
Effective SQL:编写高质量SQL语句的61个有效方法 AW.Effective.SQL.61.Specific.Ways.to.Write.Better.SQL.
Effective.Unit.Testing(2013.2).pdf 挺好的一本介绍UT的书
Effective AWK Programming:Awk 编程的经典著作
Effective Java读书笔记,记载了大部分我觉的有用的东西,前半部分有代码说明,但后半部分的代码,太过琐碎,就没有整理
《Effective Java》读书分享.pptx
【Effective Java】阅读笔记markdown 文件
266第6章 掌握前端基础 291Effective前端25:掌握同源策略和跨域 291Effective前端26:掌握前端本地文件操作与上传 299Effective前端27:学会常用的CSS居中方式 310Effective前端28:学会常用的CSS布局技术 320...
15. 使类和成员的可访问性最小化 16. 在公有类中使用访问方法而非公有域 17.使可变性最小化:不可变类