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. POJ 1094 Sorting It All Out 【拓扑排序】

    <题目链接> 题目大意: 对于N个大写字母,给定它们的一些关系,要求判断出经过多少个关系之后可以确定它们的排序或者排序存在冲突,或者所有的偏序关系用上之后依旧无法确定唯一的排序. 解题分析 ...

  2. RabbitMQ实战经验分享

    前言 最近在忙一个高考项目,看着系统顺利完成了这次高考,终于可以松口气了.看到那些即将参加高考的学生,也想起当年高三的自己. 下面分享下RabbitMQ实战经验,希望对大家有所帮助: 一.生产消息 关 ...

  3. 向cmd中添加字体的方法

    首先下载字体到C:\Windows\Fonts中,然后参考 http://blog.csdn.net/bbirdsky/article/details/38495661 中所讲的方法进行添加.

  4. linux 学习笔记 APACHE安装总结

    #cd /usr/local #mkdir APACHE #tar zxvf /usr/etc/DEV/httpd-2.2.9.tar.gz #mv httpd-2.2.9/* . #rm -rf h ...

  5. Err.number错误号和可捕获的 Microsoft access 数据库引擎和 DAO错误说明

    错误码        信息2420        数字语法错误2421        日期语法错误2422        字符串语法错误2423        ‘.’.‘!’.或 ‘()’的使用无效2 ...

  6. Linux系统模式之间的转换

    1.默认开机进入文本模式 如果想让开机自动进纯文本模式, 修改/etc/inittab 找到其中的 id:5:initdefault: 这行指示启动时的运行级是5,也就是图形模式 改成3就是文本模式了 ...

  7. MySql主键不区分大小写问题、查询不区分大小写问题

    一.问题一:MySql默认主键不区分大小写 实例: -- 创建混合类型 create table PlainText( Content nvarchar(50) , primary key(Conte ...

  8. C++ Primer 与“类”有关的注意事项总结

    C++ 与"类"有关的注意事项总结(一) 1. 除了静态 static 数据成员外,数据成员不能在类体中被显式地初始化. 例如 : class First { int memi = ...

  9. World Finals 2017爆OJ记

    Day-Inf: 去年China-Final一道数据结构题的FB送我进WF. 今年课表意外地满,好几天都是早上8点一直上课上到晚上9点,作业也相对较多.敝队大约每个星期只能训练一个下午,有时候甚至一整 ...

  10. g++ 动态库的编译及使用

    #ifndef __HELLO_H_ #define __HELLO_H_ void print(); #endif #include "hello.h" #include < ...