Tips

书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code

注意,书中的有些代码里方法是基于Java 9 API中的,所以JDK 最好下载 JDK 9以上的版本。

64. 通过接口引用对象

条目 51中指出,应该使用接口而不是类作为参数类型。更通常地说,应该更喜欢使用接口而不是类来引用对象。如果存在适当的接口类型,那么应该使用接口类型声明参数、返回值、变量和属性。真正需要引用对象的类的惟一时机是使用构造方法创建它的时候。为了具体说明这一点,考虑LinkedHashSet的情况,它是Set接口的一个实现。养成这样的习惯:

// Good - uses interface as type
Set<Son> sonSet = new LinkedHashSet<>();

不要是下面这个样子:

// Bad - uses class as type!
LinkedHashSet<Son> sonSet = new LinkedHashSet<>();

如果养成了使用接口作为类型的习惯,那么你的程序将更加灵活。如果决定要切换实现,只需在构造方法中更改类名(或使用不同的静态工厂)。例如,第一个声明可以改为:

Set<Son> sonSet = new HashSet<>();

所有的代码都会继续工作。周围的代码不知道旧的实现类型,所以它不会注意到这一变化。

有一点需要注意:如果原始实现提供了接口的常规约定不需要的某些特殊功能,并且代码依赖于该功能,那么新实现提供相同的功能至关重要。 例如,如果围绕第一个声明的代码依赖于LinkedHashSet的排序策略,那么在声明中用HashSet替换LinkedHashSet是不正确的,因为HashSet不保证迭代顺序。

那么,为什么要更改实现类型呢?因为第二个实现比原来的实现提供了更好的性能,或者因为它提供了原来的实现所缺乏的理想功能。例如,假设一个属性包含一个HashMap实例。将其更改为EnumMap将提供更好的性能和与键的自然顺序一致的迭代顺序,但是只能在键类型为枚举类型的情况下使用EnumMap。将HashMap更改为LinkedHashMap将提供可预测的迭代顺序,性能与HashMap相当,而不需要对键类型作出任何特殊要求。

你可能认为使用变量的实现类型声明变量是可以的,因为可以同时更改声明类型和实现类型,但是不能保证这种更改能否正常编译。如果客户端代码对原始实现类型使用了替换时不存在的方法,或者客户端代码将实例传递给需要原始实现类型的方法,那么在进行此更改之后,代码将不再编译。使用接口类型声明变量可以保持诚实可靠。

如果不存在适当的接口,则通过类而不是接口引用对象是完全合适的。 例如,考虑值类,例如String和BigInteger。 值类很少用多个实现类来编写。 它们通常是final的,很少有相应的接口。 将这样的值类用作参数,变量,属性或返回类型是完全合适的。

没有适当接口类型的第二种情况是属于框架的对象,其基本类型是类而不是接口。 如果一个对象属于这样一个基于类的框架,最好用相关的基类来引用它,它通常是抽象类,而不是它的实现类。 许多java.io包下的类(如OutputStream)都属于此类。

没有适当接口类型的最后一种情况是实现接口的类,但也提供了在接口中找不到的额外方法——例如,PriorityQueue具有Queue接口上不存在的comparator方法。 只有当程序依赖于额外的方法时,才应该使用这样的类来引用它的实例,这种情况应该是非常少见的。

这三种情况并不是面面俱到的,而仅仅是为了传达通过合适的类引用对象的情况。在实践中,给定对象是否具有适当的接口应该是显而易见的。如果是这样,使用接口引用对象,程序将更加灵活和流行。如果没有合适的接口,就使用类层次结构中提供所需功能的最小的具体类。

Effective Java 第三版——64. 通过对象的接口引用对象的更多相关文章

  1. Effective Java 第三版——6. 避免创建不必要的对象

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

  2. Effective Java 第三版——14.考虑实现Comparable接口

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

  3. Effective Java 第三版——21. 为后代设计接口

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

  4. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  5. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  6. effective Java 第三版学习笔记

    创建对象类型的 1,静态工厂方法代替构造器 静态工厂方法有名称,不容易混乱他的作用 不必再每次调用他的时候创建实例,创建实例的代价是高的,可以重复利用缓存的对象 静态工厂甚至能返回子类对象,例如在接口 ...

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

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

  8. Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性

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

  9. Effective Java 第三版——7. 消除过期的对象引用

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

随机推荐

  1. Manjaro (KDE)安装踩坑记录

    1.如果双显卡无法安装系统可以进如BIOS屏蔽显卡后进入安装 2.如果安装kde版本后容易冻屏.死机,可以尝试安装闭源驱动 3.如果出现resolving time out 10000ms 这样的问题 ...

  2. python实现简单工厂模式

    python实现简单工厂模式 模式定义 简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式.在简单工 ...

  3. Linux命令集

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  4. Java内存管理-掌握自定义类加载器的实现(七)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分析了ClassLoader的类加载相关的核心源码,也简单介绍了ClassLoa ...

  5. jmeter正则表达式提取器提取特定字符串后的全部内容

    jmeter进行JDBC请求时,请求后的响应结果在传递给下一个请求使用时,需要用到关联,也在jmeter中,关联通过正则表达式提取器实现. 但是,在JDBC请求后的响应结果中,往往需要关联的内容是只有 ...

  6. webpack 入门踩坑

    参考来源:知乎张轩 安装 先装好node和npm,因为webpack是一个基于node的项目.然后 npm install -g webpack 全局安装 还可以在当前项目里面也安装一个webpack ...

  7. Codeforces.1110F.Nearest Leaf(线段树)

    题目链接 \(dls\)讲过这道题,所以这不是线段树裸题吗,这场没打气气气气气=-= 现在是写着玩=v= \(Description\) 给定一棵\(n\)个点的树.\(q\)次询问,每次询问给定\( ...

  8. vue的生存周期

    钩子函数 created 实例已经创建 befoCompile 编译之前 compiled 编译之后 ready 插入到文档 beforeDestroy 销毁之前 destroyed 销毁之后

  9. python网络编程(十二)

    协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元. 为啥说他是一个执行单元,因为他自带CPU上下文.这样只要在合适的时 ...

  10. Gird Layout代码解释

    <div class="wrapper"> <!--定义一个类名为wrapper的div盒子--> <div class="one" ...