38:检查参数的有效性

每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制,在方法的开头处对参数进行检查,并且把这些限制写入文档。

注意:

  1. 对于公有方法,应该使用@throws标签在文档中说明违反参数值限制会抛出的异常
  2. 对于非公有的方法,通常使用断言来检查他们的参数:断言如果失败,抛出AssertionError;如果没有起到作用,本质上也不会有成本开销
    private void sort(long a[]){
    assert a != null;
    }
  3. 对于构造函数中的,或者参数将会被保存,后面还会用到的,尤其应该注意检查有效性

39:必要时进行保护性拷贝

如果类具有从客户端得到或者返回到客户端的可变组件,类就必须保护性的拷贝这些组件。除非拷贝成本收到限制,且类信任他的客户端不会不恰当的修改组件,就可以在文档中指明客户端的不得不恰当的修改组件,以代替保护性拷贝。

注意:

  1. 从客户端获取的可变组件也应该保护性拷贝,尤其在给构造函数传参时,这点平时没有注意到。而且,保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象,而不是原始对象,这样可以避免检查到真正拷贝期间,数据被其他线程更改。这也很好的体现了:安全大于效率
  2. 对于从客户端获取的可变组件,如若其是可以被子类化的,那么就不能使用clone函数进行拷贝,因为可能传进来的是个子类对象,而clone函数可以被子类重写,从而引发安全问题。传出去的可以使用clone,因为在类的内部可以确定它是非子类的
  3. 真正应该注意的是:只要有可能,都应该使用不可变对象作为内部组件,以避免保护性拷贝。比如,使用Date.getTime()得到的long对象作为内部的时间组件,而不是Date,因为Date可变,而long不可变

40:谨慎的设计方法签名

设计签名方法的要点:

  1. 选择合理的方法名称:遵循标准习惯与含义清晰
  2. 避免过于追求提供便利的方法以导致方法过多,尤其对于接口。除非被经常用到的操作才考虑提供便捷方法
  3. 避免过长的参数列表
    1. 拆分方法,但应注意方法的正交性以减少方法的个数,即把方法A、B拆成a,b,c三个方法,a和c实现A,b和c实现B
    2. 创建辅助类用来保存参数的分组,一般为静态成员类。尤其当某些参数经常一起出现时
    3. 采用Builder模式:多次调用setter设置参数,然后执行方法

注意:

  1. 对于参数类型,若可以,优先使用接口而不是类,以避免昂贵的拷贝操作
  2. 对于boolean参数,优先使用两个元素的枚举类型,以使代码更易阅读和编写,且具有更好的扩展性

41:慎用重载

重载是静态的,编译时根据调用的参数决定使用重载函数的哪个版本;覆盖是动态的,运行时根据实例的实际类型决定使用哪个版本。

更加准确的说,应该避免的重载是指:参数个数相同,且不同版本的形参之间通过类型转换就可以适用不同的版本,这样就使得程序员不是很容易就确定到底调用哪个版本,从而可能导致错误。

如果需要重载,最好:

  1. 使不同版本具有不同的形参个数
  2. 如果具有相同的形参个数,那么不同版本的形参是“根本不同的类型”,让人一看就知道调用哪个,比如int和List<int>,而不是int与Integer,因为他们二者会自动拆装箱
  3. 如果还不行,那么应该尽量保证不同版本的重载函数对于相同的形参,所产生的行为一致
  4. 考虑不使用重载,而使用不同的命名,比如ObjectOutputStream有writeBoolean、writeLong、writeInt这些方法,也是一种很好的策略

42:慎用可变参数

可变参数可以接受0个或者多个指定类型的参数。可变参数机制通过先创建一个数组,数组的大小为在调用位置所传递的参数数量,然后将参数值传到数组中,最后将数组传递给方法。在定义参数数目不定的方法时,可变参数是一种很方便的方式,但不应该被滥用,以免造成混乱。造成混乱的原因可能大多出于:

  1. 可以传递0个参数,即不传参数
  2. 当参数类型定义为T时。比如如果参数定义为T... args,调用时传入的是int[],但是由于int是基本类型,而不能直接看做对象T,所以将会把int[]整体当做一个参数,而不是多个int参数

另外,当重视性能,认为可变参数的每次调用进行的数组分配和初始化可能难以满足性能要求时,可以考虑如下方式:如果对某个方法95%的调用会有三个或者更少的参数,就声明该方法的5个重载:

 public void fun() {}
public void fun(int a1) {}
public void fun(int a1, int a2) {}
public void fun(int a1, int a2, int a3) {}
public void fun(int a1, int a2, int a3, int... rest) {}

43:返回零长度的数组或者集合,而不是null

这个是对于返回类型为数组或者集合的方法来说的,

好处:返回零长度的数组或者集合,就不要求客户端要有额外的代码来处理null返回值的情况。

对于返回null可能比零长度数组或集合的性能优势的反驳:

  1. 这样级别的性能担心是不明智的,除非确定造成了性能问题
  2. 因为零长度的数组或集合是不可变的,而不可变对象是有可能自由共享的,即多次调用也只会生成一个零长度的数组或集合

44:为所有导出的API元素编写文档注释

  1. 使用Javadoc进行注释,包括所有导出的类、接口、构造器、方法或域
  2. 对于方法,简洁的描述它和客户端之间的约定,说明这个方法做了什么,而不是如何完全的,以前所有的前提条件、后置条件、副作用以及线程安全性

Effective Java 阅读笔记——方法的更多相关文章

  1. Effective Java阅读笔记——引言

    “我很希望10年前就拥有这本书.可能有人认为我不需要任何Java方面的书籍,但是我需要这本书.” ——Java之父 James Gosling 在图书馆找到这本java著作时,首先看到了这句话.   ...

  2. Effective Java 阅读笔记——并发

    66:同步访问共享的可变数据 synchronized:1互斥,阻止线程看到的对象处于不一致的状态:2保证线程在进入同步区时能看到变量的被各个线程的所有修改 Java中,除了long或者double, ...

  3. Effective Java 阅读笔记——枚举和注解

    30:用enum代替int常量 当需要一组固定常量的时候,应该使用enum代替int常量,除了对于手机登资源有限的设备应该酌情考虑enum的性能弱势之外. 31:用实例域代替序数 应该给enum添加i ...

  4. 《Effective Java》笔记45-56:通用程序设计

    将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 要使用局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方才声明,不要过早的声明. 局部变量的作用域从它被声明的 ...

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

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

  6. Effective Java 读书笔记(一):使用静态工厂方法代替构造器

    这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...

  7. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  8. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  9. Effective Java要点笔记

    第一章: 创建和销毁对象 类可以通过静态工厂方法来提供客户端,而不是通过构造器 优点: 自定义工厂名称,提高可读性 可以工厂里搞单例 控制实例类是哪种子类 总之是更加灵活,可读性更高 缺点: 有可能会 ...

随机推荐

  1. Spring MVC 3.x 基本配置

    WEB-INF/web.xml 例1 <?xml version="1.0" encoding="UTF-8"?> <web-app xmln ...

  2. 斜堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了斜堆,本章给出斜堆的Java版本.还是那句老话,三种实现的原理一样,择其一了解即可. 目录1. 斜堆的介绍2. 斜堆的基本操作3. 斜堆的Java实现(完整源码)4. ...

  3. 【转载】Ubuntu下SVN安装和配置

    一.SVN安装 1.安装包 1.$ sudo apt-get install subversion 2.创建项目目录 $ sudo mkdir /home/xiaozhe/svn $ cd /home ...

  4. Office Web Apps Server 概述

    Office Web Apps Server 是新的 Office 服务器产品,它提供 Word.PowerPoint.Excel 和 OneNote 的基于浏览器的版本.单个 Office Web ...

  5. 基于selenium的pyse自动化测试框架

    WebUI automation testing framework based on Selenium 介绍: pyse基于selenium(webdriver)进行了简单的二次封装,比seleni ...

  6. python读取xml文件

    关于python读取xml文章很多,但大多文章都是贴一个xml文件,然后再贴个处理文件的代码.这样并不利于初学者的学习,希望这篇文章可以更通俗易懂的教如何使用python 来读取xml 文件. 什么是 ...

  7. 新开博客 http://wylhyz.github.io/

    刚刚使用hexo在github pages上建立了静态博客,地址 http://wylhyz.github.io/

  8. 我也想聊聊 OAuth 2.0 —— 基本概念

    这是一篇待在草稿箱半年之久的文章 连我自己都不知道我的草稿箱有多少未发布的文章了.这应该是我在上一家公司未解散之前写的,记得当时是要做一个开发者中心,很不幸. 今天,打开草稿箱有种莫名的伤感,看到这个 ...

  9. ASP.NET MVC 快速开发框架之 SqlSugar+SyntacticSugar+JQWidgetsSugar+jqwidgets

    jqwidgets.js: 是一个功能完整的框架,它具有专业的可触摸的jQuery插件.主题.输入验证.拖放插件.数据适配器,内置WAI-ARIA(无障碍网页应用)可访问性.国际化和MVVM模式支持. ...

  10. 通过Foxit和坚果云实现iPad和PC的pdf同步阅读(修改,笔记)

    这是解决我之后上班地铁上看书问题的一个关键部分 一个手持电子设备,不大不小 一个方便做笔记的笔 一个方便做笔记的阅读器软件 方便快速地同步(只同步标记最好了) 在查看很多建议以及自己尝试之后,总结了这 ...