编写高质量代码:改善Java程序的151个建议-学习笔记(5-8章)
2017-05-13 20:26
721 查看
枚举和注解
83.推荐使用枚举定义常亮
public enum SeaSon { Sping, Summer, Autumn, Winner; public static SeaSon getCommonSeason() { return Sping; } } for (SeaSon s : SeaSon.values()) { Log.i("clp", "s values =" + s); } Log.i("clp", "common =" + SeaSon.getCommonSeason());
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Sping
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Summer
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Autumn
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Winner
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: common =Sping
84.使用构造函数协助描述枚举项
public enum SeaSon { Sping("春"), Summer("夏"), Autumn("秋"), Winner("冬"); private String desc; SeaSon(String desc) { this.desc = desc; } public String getDesc() { return desc; } public static SeaSon getCommonSeason() { return Sping; } }
for (SeaSon s : SeaSon.values()) { Log.i("clp", "s values =" + s.getDesc()); } Log.i("clp", "common =" + SeaSon.getCommonSeason());
构造函数还可以比这个更复杂,传递对象等。
85.小心switch带来的空值异常
public void doSwSeaSon(SeaSon seaSon) { switch (seaSon) { case Sping: Log.i("clp", "Sping"); break; default: Log.i("clp", "其他类型"); break; } }
doSwSeaSon(null);
java.lang.NullPointerException: Attempt to invoke virtual method ‘int com.cp.demo.java.SeaSon.ordinal()’ on a null object reference
case的其实是:SeaSon.Sping.ordinal(),所以要做对象的空值判断。
86.在switch的default代码块中增加AssertionError错误
因为枚举类型和case没有强制关系,如果后续增加了一个,没有case,就会导致switch漏掉这个枚举项。87.枚举使用valueOf前必须进行校验
否则会抛出异常List<String> mList = Arrays.asList("Sping", "sss"); for (int i = 0; i < mList.size(); i++) { SeaSon sea = SeaSon.valueOf(mList.get(i)); if (sea == null) { Log.i("clp", "没有此枚举值"); } else { Log.i("clp", "有值"); } }
java.lang.IllegalArgumentException: sss is not a constant in com.cp.demo.java.SeaSon
两种方案:
1.捕获异常
List<String> mList = Arrays.asList("Sping", "sss"); for (int i = 0; i < mList.size(); i++) { try { SeaSon sea = SeaSon.valueOf(mList.get(i)); Log.i("clp", "有值"); } catch (IllegalArgumentException e) { Log.i("clp", "没有此枚举值"); } }
04-19 11:35:20.148 13538-13538/com.example.demo I/clp: 有值
04-19 11:35:20.148 13538-13538/com.example.demo I/clp: 没有此枚举值
2.拓展枚举类
public static boolean contains(String name) { for (SeaSon sen : values()) { if (sen.name().equals(name)) { return true; } } return false; }
List<String> mList = Arrays.asList("Sping", "sss"); for (int i = 0; i < mList.size(); i++) { boolean sea = SeaSon.contains(mList.get(i)); if (sea) { Log.i("clp", "有值"); } else { Log.i("clp", "没有此枚举值"); } }
88.用枚举实现工厂方法模式更简洁
1.非静态方法实现。public interface Car { public void drive(); } public class FortCar implements Car { @Override public void drive() { Log.i("clp", "fort drive"); } } public class BuickCar implements Car { @Override public void drive() { Log.i("clp", "buick drive"); } } public enum CarFactory { FortCar, BuickCar; public Car create() { switch (this) { case FortCar: return new FortCar(); case BuickCar: return new BuickCar(); default: Log.i("clp", "无效参数"); } return null; } }
04-19 11:55:34.988 1940-1940/com.example.demo I/clp: fort drive
2.通过抽象方法生成
public enum CarFactory { FortCar { @Override public Car create() { return new FortCar(); } }, BuickCar { @Override public Car create() { return new BuickCar(); } }; public abstract Car create(); }
89.枚举项的数量限制的64个以内
long e = -1L >>> -65;//value=1 long e = -1L >>> -1;//value=1 long e = -1L >>> 63;//value=1 long e = -1L >>> 1;//9223372036854775807 long e = -1L >>> 62;//value=3 int e = -1 >>> 31;//value=1 int e = -1 >>> 1;//2147483647
小于等于64和大于64处理的机制是不一样的。
Enum[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); RegularEnumSet: void addAll() { if (universe.length != 0) elements = -1L >>> -universe.length; } JumboEnumSet: void addAll() { for (int i = 0; i < elements.length; i++) elements[i] = -1; elements[elements.length - 1] >>>= -universe.length; size = universe.length; }
所以内部是以64位拆分进行分组。
90.小心注解继承
91.枚举和注解结合使用威力很大
92.注意@Overrig不同版本的区别
如果是Java1.6版本的程序移植到1.5版本环境中,就需要删除实现接口方法上的@Override注解泛型和反射
93.Java的泛型是类型擦除的
java的编译期和运行期解读:http://www.360doc.com/content/14/0218/23/9440338_353675002.shtml
编译期:源码->class文件的过程
运行期:在JVM中运行的过程
public void initList(List<Integer> mList) { } public void initList(List<String> mList) { }
按照上面这种方式写,报错。
initList(List)’ clashes with ‘initList(List)’; both methods have same erasure
List<String> mList = new ArrayList<String>(); List<Integer> mIList = new ArrayList<Integer>(); Log.i("clp", "is equals=" + (mList.getClass() == mIList.getClass()));
04-25 15:49:13.356 2760-2760/old.pkg.com.myapplicati I/clp: is equals=true
他们擦除后的类型都是List
Java泛型-类型擦除:
http://blog.csdn.net/caihaijiang/article/details/6403349
94.不能初始化泛型参数和数组
T t = new T();//报错 T[] mTArray = new T[];//报错 List<T> mList = new ArrayList<T>();//报错
以上3个写法,在AS上面都报错,需要在运行期指定T类型。
95.强制声明泛型的实际类型
“`List mList = CldCalMiniUtil.asList();//正确
List mList = CldCalMiniUtil.asList();//正确
List mList2 = CldCalMiniUtil.asList(1, 2.2);//报错
List mList2 = CldCalMiniUtil.asList(1, 2.2);//正确–这里使用了强制声明
相关文章推荐
- 编写高质量代码:改善Java程序的151个建议-学习笔记(9-12章)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(1-4章)
- 编写高质量代码:改善Java程序的151个建议-学习笔记(1-4章)
- 《编写高质量代码改善Java程序的151个建议》学习笔记 第6章 枚举和注解
- 编写高质量代码:改善java程序的151个建议-----笔记(1)
- 读编写高质量代码--改善java程序的151个建议笔记
- 笔记:编写高质量代码 改善Java程序的151个建议
- [编写高质量代码:改善java程序的151个建议]建议43 避免对象浅拷贝; 建议44:推荐使用序列化实现对象的深拷贝
- [编写高质量代码:改善java程序的151个建议]建议35:不要在类中初始化其他类
- 编写高质量代码++改善Java程序的151个建议
- [编写高质量代码:改善java程序的151个建议]建议58 强烈建议使用UTF-8编码
- [编写高质量代码:改善java程序的151个建议]建议53 注意方法中传递的参数要求
- [编写高质量代码:改善java程序的151个建议]建议62 警惕数组的浅拷贝
- 编写高质量代码:改善Java程序的151个建议 (第2章 基本类型)
- 编写高质量代码:改善Java程序的151个建议 (第3章 类、对象及方法)
- [编写高质量代码:改善java程序的151个建议]建议34:构造函数尽量简化
- 编写高质量代码:改善Java程序的151个建议