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

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

  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. MQTT--mosquitto使用详解

    mosquitto_pub(发布)的用法 用法: mosquitto_pub [-d] [-h hostname] [-i client_id] [-I client id prefix] [-p p ...

  2. Qt Creator中增加新的ui文件时报错

    原因分析:moc_开头的文件编译过程中没有又一次生成导致. 解决的方法:删除编译产生的build目录.又一次编译就可以. 错误类型截图例如以下: 这个问题的解决.使得能够在不论什么时候都能够在proj ...

  3. shell 判断问题总结

    #!/bin/bash #比如需要判断一个变量是否含有值: if [[ -z $1 ]] ; thenecho "Something like empty!"exit 0;fi # ...

  4. Pig系统分析(7)-Pig有用工具类

    Explain Explain是Pig提供的调试工具,使用explain能够输出Pig Lation的运行计划.值得一提的是,explain支持-dot选项.将运行计划以DOT格式输出, (DOT是一 ...

  5. 创建自己的Spring Boot Starter

    抽取通用模块作为项目的一个spring boot starter.可参照mybatis的写法. IDEA创建Empty Project并添加如下2个module,一个基本maven模块,另一个引入sp ...

  6. 解决Tomcat下连接Oracle报错"Error while registering Oracle JDBC Diagnosability MBean."

    Tomcat不失为一个好的开发学习容器,但使用Oracle 11g自带的JDBC驱动ojdbc6.jar和JDK6一起运行的时候,特别是和spring框架一起使用会报错:SEVERE: Error w ...

  7. FastDFS分布文件系统

    FastDFS是为互联网应用量身定做的一套分布式文件存储系统,非常适合用来存储用户图片.视频.文档等文件.对于互联网应用,和其他分布式文件系统相比,优势非常明显.具体情况大家可以看相关的介绍文档,包括 ...

  8. UFLDL深度学习笔记 (六)卷积神经网络

    UFLDL深度学习笔记 (六)卷积神经网络 1. 主要思路 "UFLDL 卷积神经网络"主要讲解了对大尺寸图像应用前面所讨论神经网络学习的方法,其中的变化有两条,第一,对大尺寸图像 ...

  9. iOS中 HTTP/Socket/TCP/IP通信协议具体解释 韩俊强的博客

    简介: // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 / ...

  10. LINQ to Tree - A Generic Technique for Querying Tree-like Structures,包含遍历WPF VisualTree

    https://www.codeproject.com/Articles/62397/LINQ-to-Tree-A-Generic-Technique-for-Querying-Tree#generi ...