第三十八条:检查参数的有效性

第三十九条:必要时进行保护性拷贝

  public class Period {
private final Date start;
private final Date end; public Period(Date start, Date end) {
this.start = start;
this.end = end;
} public Date start() {
return start;
} public Date end() {
return end;
}
}

写完上面的代码后会认为这是一个很安全的了,不可变,初始化了之后就不可以start和end就不可以改变了,but,真这样?注意Date是可变的

      Date start = new Date();
Date end = new Date();
Period period = new Period(start, end);
end.setTime(System.currentTimeMillis());

这样就把原本的时间改变了。

  public class Period {
private final Date start;
private final Date end; public Period(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
} public Date start() {
return new Date(start.getTime());
} public Date end() {
return new Date(end.getTime());
}

程序改成这样后,这个类就真的不可变了,穿件和向客户端返回数据的时候都不是本身的引用,而是另一个实例。这里也没用,如果用clone方法,客户端还可能编写Date的子类,如果在子类里包含攻击代码,如在子类的实例被创建的时候把指向该实例的引用记录到一个私有的静态列表中。

第四十条:谨慎设计方法签名
这个是对设计API的技巧

  • 谨慎的选择方法的名称
  • 不要国语追求提供遍历的方法。意思是不要暴露过多的方法,这样会很难学习、使用、文档化。只要提供这个类应该提供的方法就可以了。
  • 避免过长的参数列表。

三种方法缩短参数

  • 把方法分解多个小方法
  • 创建辅助类
  • 采用建造者模式(Builder)。前面的有例子,就在类内部建造一个Builder类,在这个里设计各种参数,是根据方法设置的参数已读。外部类的构造器将内部Builder的类的参数赋值给外部类。

对于boolean类型,优先采用enum。

第四十一条:慎用重载
看一下下面的例子

  class CollecitonClassifier {
public static String classify(Set<?> s) {
return "Set";
}
public static String classify(List<?> s) {
return "List";
}
public static String classify(Collection<?> s) {
return "Unknown";
}
public static void main(String[] args) {
Collection<?>[] collections ={new HashSet<String>(), new ArrayList<String>(), new HashMap<String, String>().values()};
for (Collection<?> collection : collections)
System.out.println(FourtyFirst.CollecitonClassifier.classify(collection));
}
}

期望的结果是"Set" "List" "Unknown",但是上面的结果是三个Unknown。在看下面的例子

  class Wine{
String name(){return "wine";}
}
class Champagne extends Wine{
@Override
String name(){return "Champagne";}
}
public void test() {
Wine[] wines = {new Wine(), new Champagne()};
for (Wine wine : wines)
System.out.println(wine.name());
}

这样就是所期望的结果"Wine" "Champagne"
为什么第一个的输出和想的不一样,在声明类型的时候声明出来的最终结果就是Collection类型的,因此最终就是进入 public static String classify(Collection<?> s) {}这个方法。而下面方法的覆盖就能根据类型找到具体的方法。
对于重载方法的选择是静态的,而对于覆盖的选择是动态的。对于重载,在编译时就已经确定了类型(Collection)。而对于方法覆盖,是在运行时才知道当前是什么类型,根据类型类确定到底调用哪个类的方法。
还有在用Set和List时要注意,Set有remove(i) 和remove(E)方法,如果你的Set中放的是Integer,注意一下这个地方,很可能想移除的是Set中的元素,而却调用了remove(i)的方法,移除的是索引为i的。List同样要注意。
为了避免重载方法出现的问题,最好不要出现相同参数个数的重载方法,起个其他的名字又不是难事。

第四十二条:慎用可变参数
int sum(int ...arg) {}  可变参数就是这种类型的参数。

第四十三条:返回零长度的数组或者集合,而不是null

第四十四条:为所有导出的API元素编写文档注释

Effective java -- 6 方法的更多相关文章

  1. effective java —— 终结方法守卫者

    目录: effective java —— 终结方法守卫者 effective java 第2章:创建和销毁对象.第7条 : 避免使用终结方法.最后的“终结方法守卫者 (finalizer guard ...

  2. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  3. Effective Java 学习笔记之第七条——避免使用终结(finalizer)方法

    避免使用终结方法(finalizer) 终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的. 不要把finalizer当成C++中析构函数的对应物.java中,当对象不 ...

  4. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Effective Java 第三版——10. 重写equals方法时遵守通用约定

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——12. 始终重写 toString 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  8. Effective Java 第三版——13. 谨慎地重写 clone 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——16.在公共类中使用访问方法而不是公共属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. Maven学习小结

    简介:一款服务于Java的自动化构建工具 1 安装 必须已经安装了jdk且配置了环境变量,注意查看当前maven版本支持的jdk版本 配置Maven的环境变量 MAVEN_HOME PATH 使用mv ...

  2. sqlserver修改表主键自增

    alter table tname add id int  identity(1,1)

  3. PSSM特征-从生成到处理

    以下代码均为个人原创,如有疑问,欢迎交流.新浪微博:拾毅者 本节内容: pssm生成 pssm简化 标准的pssm构建 滑动pssm生成 在基于蛋白质序列的相关预測中.使用PSSM打分矩阵会得将预測效 ...

  4. Dual Camera Info

    一个摄像头解决不了的问题,那就用两个:对于双摄你需要了解这些 http://www.chengshiluntan.com/wg/a/20160715/6ca0343f59789235c9419887f ...

  5. 解析spark RDD

    RDD是spark抽象的基石,可以说整个spark编程就是对RDD进行的操作   RDD是弹性的分布式数据集,它是只读的,可分区的,这个数据集的全部或者部分数据可以缓存在内存中,在多次计算间重用.所谓 ...

  6. Redis的订阅发布

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using ServiceS ...

  7. oracle快速复制表数据

    方法一: 只复制表结构: create table table_name_new as select * from table_name_old where 1=2; 然后: alter sessio ...

  8. ”非常危险“的Linux命令

    Linux命令是一种很有趣且有用的东西,但在你不知道会带来什么后果的时候,它又会显得非常危险.所以,在输入某些命令前,请多多检查再敲回车. rm –rf rm –rf是删除文件夹和里面附带内容的一种最 ...

  9. ARM初学引导_转

    一直都在听说ARM有多么好,有多神奇,有多难学.故学它时都兴奋加恐惧.呵呵,我刚好用ARM也有一段时间了.写点东西给ARM的初学者,希望能起到帮助作用. 1,记住:ARM很简单,就如从51转换到PIC ...

  10. MIC中示例程序计算π

    mic中编程十分简单,只需在普通程序中简单加几句就可以,使用 lspci|grep -i -co-processor 命令可以查看机器中是否插入MIC卡以及MIC卡的数目,MIC编程环境的配置这里就不 ...