Effective Java 2 读书笔记 第7章 方法
编程技术  /  houtizong 发布于 3年前   75
当编写方法或者构造器的时候,应该考虑它的参数有哪些限制。应该把这些限制写到文档中,并且在每个方法的开头处,通过显示的检查来实施这些限制。即应该在发生错误之后尽快检测出错误 ,可以避免很多异常和不正确的却无法检测的结果。
通过进行有效性检查,付出的努力远远小于带来的异常。
例外 :有效检查工作非常昂贵。
但并不是意味着,对参数的任何限制都是好事,相反,在设计方法时候,应该使得他们尽可能通用,并符合实际的需要。然而在通常情况下,有的限制对被实现的抽象来说是固有的。
总之:如果类具有从客户端得到或者返回到客户端的可变组件,类就必须保护性地拷贝这些组件。如果拷贝的成本收到限制,并且类信任它的客户端不会不恰当地修改足球,就可以在文档中指名客户端的职责是不得修改受影响的组件,以此来代替保护性拷贝
看下面的程序,
// Broken! - What does this program print?public class CollectionClassifier {public static String classify(Set<?> s) {return "Set";}public static String classify(List<?> lst) {return "List";}public static String classify(Collection<?> c) {return "Unknown Collection";}public static void main(String[] args) {Collection<?>[] collections = {new HashSet<String>(),new ArrayList<BigInteger>(),new HashMap<String, String>().values()};for (Collection<?> c : collections)System.out.println(classify(c));}}
我们期望的是打印Set,List, Unknown Collection,然后确实三次“Unknown Collection”
因为对于重载方法(overloaded method)的选择是静态(编译时)的,而对于覆盖(overriden method)的方法的选择是动态(运行时)的
可变参数方法可以接受0个或者多个指定类型的参数
// Simple use of varargsstatic int sum(int... args) {int sum = 0;for (int arg : args)sum += arg;return sum;}
有时候会有这样的需求,需要一个或者多个某种类型参数的方法,这时候需要指定一个正常参数和一个可变参数比较好
// The WRONG way to use varargs to pass one or more arguments!static int min(int... args) {if (args.length == 0)throw new IllegalArgumentException("Too few arguments");int min = args[0];for (int i = 1; i < args.length; i++)if (args[i] < min)min = args[i];return min;}
因为可变参数的这个特性,我们可以讲数组当作final参数的现有方法,改造成可变参数代替,而不影响现有的客户端,然后可以并不意味着应该这么做,Arrays.asList就会出现不恰当的使用
对于:
public static void main(String[] args) {int[] digits = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };System.out.println(Arrays.asList(digits));}
Arrays.asList将digits的对象引用包装到了List<int[]>中,而不是我们想要的那种每一个元素都包装,要想产生这种结果,可以这样:
// The right way to print an arraySystem.out.println(Arrays.toString(myArray));
因此 不必改造具有final数组参数的每个方法,只有当确实是在数量不顶的值上执行调用时使用可变参数
对于重视性能的程序来说,使用可变参数更要小心,如果某个方法的95%调用会有≤3个参数,则重载5个,超过了的用可变参数,如
public void foo() { }public void foo(int a1) { }public void foo(int a1, int a2) { }public void foo(int a1, int a2, int a3) { }public void foo(int a1, int a2, int a3, int... rest) { }
在定义参数数目不定的方法时,可变参数是一种很方便的方式,但是不能被滥用
返回null值会要求客户端中必须有额外的代码来处理null返回值,例如:
private final List<Cheese> cheesesInStock = ...;/*** @return an array containing all of the cheeses in the shop,* or null if no cheeses are available for purchase.*/public Cheese[] getCheeses() {if (cheesesInStock.size() == 0)return null;...}
客户端需要:
Cheese[] cheeses = shop.getCheeses();if (cheeses != null &&Arrays.asList(cheeses).contains(Cheese.STILTON))System.out.println("Jolly good, just the thing.");}
而不是:
if (Arrays.asList(shop.getCheeses()).contains(Cheese.STILTON))System.out.println("Jolly good, just the thing.");
返回数组也不必担心性能,因为0长度数组是不可变的,可以共享,在类中可以有一个static 的0长度数组来提供使用
如:
// The right way to return a copy of a collectionpublic List<Cheese> getCheeseList() {if (cheesesInStock.isEmpty())return Collections.emptyList(); // Always returns same listelsereturn new ArrayList<Cheese>(cheesesInStock);}
如果想要一个API真正可用,就必须为其编写文档。javadoc利用特殊格式的稳定注释(documentation comment),根据源代码自动产生API文档。
详细的规范可以参考:Sun的 How to Write Doc Comments
为了正确地编写API文档,必须在每个被到处的类,接口,构造器,方法和域声明之前增加一个文档注释。如果类是序列化的,也应该对它的序列化形式编写文档。
注意事项:
简而言之:要为API编写文档,文档注释是最好的最有效的途径。
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接