effective java读书笔记
第52条:通过接口引用对象
如果有合适的接口类型存在,那么对于参数、返回值、变量和成员变量来说,就都应该使用接口类型进行声明;如果你养成了用接口作为类型的习惯,你的程序将会更加灵活,当你决定更换实现时,所要做的就只是构造器中类的名称。
有一点值得注意:如果原来的实现提供了某种特殊的功能,而这种功能并不是这个接口的通用约定所要求的,并且周围的代码又依赖于这种功能,那么新的实现也要提供相同的功能。
类实现了接口,但是提供了接口中不存在的额外的方法–例如LinkedHashMap。如果程序依赖于这些额外的方法,这种类就应该只被用来引用它的实例。
实际上,给定的对象是否具有适当的接口应该是很显然的。如果是,用接口引用对象就会使程序更加灵活;如果不是,则使用类层次结构中提供了必要功能的最基础的类。
第38条:检查参数的有效性
每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制,应该把这些限制写到文档中,并且在这个方法体的开头处,通过显式的检查来实施这些限制
第43条:返回0长度的数组或者集合,而不是Null
返回类型为数组或集合的方法没理由返回null,应该返回一个零长度的数组或者集合。
可以做成在每当需要返回空集合时,都返回同一个不可变的空集合。Collections.emptySet、emptyList、emptyMap提供的正是这种集合。public List<Person> getPersons(){ if(persons.isEmpty()){ return Collections.emptyList(); }else{ return persons; } }
第46条:for-each循环优先于传统的for循环
for-each在简洁性和预防bug方面有着传统的for循环无法比拟的优势,并且没有性能损失,应该尽可能的使用for-each循环。
有三种常见的情况无法使用for-each循环:
- 过滤:如果需要遍历集合,并删除选定的元素,就需要使用显示的迭代器,以便可以调用它的remove方法。
- 转换:如果需要遍历列表或者数组,并取代它部分或者全部的元素值,就需要列表迭代器或者数组索引,以便设定元素的值。
- 平行迭代:如果需要并行的遍历多个集合,就需要显示的控制迭代器或者索引变量,以便所有迭代器或者索引变量都可以得到同步前移。
第48条:如果需要精确的答案,请避免使用float和double
第49条:基本类型优先于装箱基本类型
基本类型和装箱基本类型之间有三个主要的区别:
- 基本类型只有值,而装箱基本类型则具有与它们的值不同的地址。换句话说,两个装箱基本类型可以具有相同的值和不同的地址。
- 基本类型只有功能完备的值,而每个装箱基本类型除了它对应的基本类型的所有功能值外,还有个非功能值:null
- 基本类型通常比装箱基本类型更节省时间和空间.
public static void main(String[] args){
Long sum = 0L;
for(long i=0;i<Integer.MAX_VALUE;i++){
sum += i;
}
System.out.println(sum);
}
这个程序运行起来比预计的要慢一些,因为它不小心将一个局部变量(sum)声明为装箱基本类型Long,而不是基本类型long,变量被反复的装箱和拆箱,导致明显的性能下降。
总之,当可以选择的时候,基本类型要优先于装箱基本类型。