Java程序设计语言提供两种机制,可以用来定义允许多个实现的类型:接口和抽象方法,这两者直接醉为明显的区别在于,抽象类允许某些方法的实现,但接口不允许,一个更为重要的区别在于,为了实现由抽象类定义的类型,类必须成为抽象类的一个子类。任何一个类,只要定义了所有必要的方法,并且遵守通用约定,它就被允许实现一个借口,而不管这个类是处于类层次的哪个位置。因为Java只允许单继承,所有抽象类作为类型定义受到类极大的限制。

  现有的类很容易被更新,以实现新的接口。

  如果你希望让两个类扩展同一个抽象类,就必须把抽象类放到类型层次结构的高处,以便这两个类的一个祖先成为它的子类。遗憾的是这样做会间接到伤害到类层次,迫使这个公共祖先到所有后代类都扩展这个新的抽象类,无论它对于这些后代类是否合适。

  接口是定义混合类型的理想选择。

  接口允许我们构造非层次结构的类型框架。

  假如我们有两个接口,一个表示歌唱家,另一个表示作曲家,在现实生活中,有很多人即是歌唱家又是作曲家,如果是接口,我只需要同时实现这两个接口就可以,如果是抽象类,因为Java是单继承的,我就没有办法描述这一类的人。

  虽然接口不允许包含方法的实现,但是,使用接口来定义类型并不妨碍你为程序猿提供实现上的帮助。通过对你导出的每个重要接口都提供一个抽象骨架的实现类,把接口和抽象类的优点都结合起来。接口的作用仍然是定义类型,但是骨架的实现类接管类所有与接口实现相关的工作。

  骨架为接口提供实现上的帮助,但又不强加“抽象类被用作类型定义时”所特有的严格限制。对于接口大多数的实现来讲,扩展骨架实现类是个很显然的选择,但不是必须的。如果预制的类无法扩展骨架实现类,这个类始终可以收工实现这个接口。此外,骨架实现类仍然有助于接口的实现。实现类这个接口的类可以把对于这个接口方法的调用,转发到一个内部私有类的实例上,这个内部私有类扩展骨架实现类。这种方法被称作模拟多重继承。这项技术具有多重继承的绝大多数有点,同时又避免了相应的缺陷。

  编写骨架实现类相对比较简单,只是有点单调乏味。首先,必须认真研究接口,并确定哪些方法时最为基本的,其他方法则可以根据它们来实现。这些方法将成为骨架实现类中的抽象方法。然后,必须为接口中的所有其他的方法提供具体实现。例如,下面是Map.Entry接口的骨架实现类:

/**
* 接口优于抽象类
* @author weishiyao
*
* @param <K>
* @param <V>
*/
// Skeletal Implementation
public abstract class AbstractMapEntry<K, V> implements Map.Entry<K, V>{ // Primitive operations
public abstract K getKey();
public abstract V getValue(); // Entries in modifiable maps must override this method
public V setValue(V value) {
throw new UnsupportedOperationException();
} // Implements the general contract of Map.Entry.equals
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Map.Entry)) {
return false;
}
Map.Entry<?, ?> arg = (Map.Entry) obj;
return equals(getKey(), arg.getKey()) && equals(getValue(), arg.getValue());
} private static boolean equals(Object obj1, Object obj2) {
return obj1 == null ? obj2 == null : obj1.equals(obj2);
} // Implements the general contract of Map.Entry.hashCode
@Override
public int hashCode() {
return hashCode(getKey()) ^ hashCode(getValue());
} private static int hashCode(Object obj) {
return obj == null ? 0 : obj.hashCode();
}
}

  骨架实现类时为了继承的目的而设计的,这种使用方式在平时开发中经常可以见到,很多框架中都有使用方式,之前为也是见过好多次框架中这么使用,大致能明白这么写是干什么,这次经过这么详细讲解,算是彻底明白为什么要这么使用了,能想到这种写法的人真的也是大神了。

  

  

EffectiveJava——接口优于抽象类的更多相关文章

  1. Effective Java 第三版—— 20. 接口优于抽象类

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

  2. 从接口、抽象类到工厂模式再到JVM来总结一些问题

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 涉及到的知识点总结如下: 为什么使用接口? 接口和抽象类的区别 简单工厂模式总结 Java中new和newInstance的区别 J ...

  3. (转)深入理解Java的接口和抽象类

    原文地址: http://www.cnblogs.com/dolphin0520/p/3811437.html 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP ...

  4. c++ 接口和抽象类

    其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...

  5. android中接口和抽象类的区别

    最近发现很多基础有点生疏了,特地写一点博客来巩固一下.今天主要来谈谈接口和抽象类的区别,我们在项目的很多地方都会用到接口或者抽象类,但是它们之间的一些区别和相同点不知道大家有没有注意到,还有就是,什么 ...

  6. 深入理解Java的接口和抽象类(转)

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  7. c#接口与抽象类的区别

    abstract 修饰符用于表示所修饰的类是不完整的,并且它只能用作基类.抽象类与非抽象类在以下方面是不同的: 抽象类不能直接实例化,并且对抽象类使用 new 运算符是编译时错误.虽然一些变量和值在编 ...

  8. Java接口和抽象类的区别

    今天看到项目中,写了一个抽象类,里面有很多方法继承了这类,当调用这个接口时,采用的是这个抽象类去调方法的,当时一想,这个不就是我们说的Java的多态的特征: 继承:存在继承关系的子类和父类 重写:子类 ...

  9. 深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

随机推荐

  1. ssh框架搭建错误集合

    1,把jsp放入到WEB-INF/view目录下,struts2.xml配置<result name="success">/WEB-INF/view/home.jsp& ...

  2. 针对 SQL Server 2008 在Windows Server 2008上的访问配置 Windows 防火墙

    现在Windows Server 2008 服务器用的越来越多,2008的防火墙比2003的有了很大的增强,安全性有了更大的提高. 甚至80端口的出站默认都是被关闭的.所以如果在2008Server上 ...

  3. What's New in iOS9 iOS9功能改进

    What's New in iOS9 This article summarizes the key developer-related features introduced in iOS 9, w ...

  4. HP P1008打印机如何打印特殊纸张

    一.问题的提出 HP P1008中间有一个进纸槽,这是干什么的? 二.问题的分析 查说明,说这个进纸槽是叫做优先进纸槽,用于各种非常规的纸张的打印. 三.问题的解决 弄一张特殊尺寸的纸张,打开要编辑的 ...

  5. 【Android】键盘的展开和收起

    键盘的展开和收起主要使用到类InputMethodManager:http://developer.android.com/reference/android/view/inputmethod/Inp ...

  6. 测试GeoGebra博客

    已知函数 \(\textit{f}(\textit{x})=2\textit{m}\ln\textit{x}-\textit{x}^2\), \(\textit{g}(\textit{x})=\tex ...

  7. log4net各种Filter使用

    log4net里面的filter类常用的为: 1.DenyAllFilter 拒绝所用的日志输出 <filter type="log4net.Filter.LevelMatchFilt ...

  8. Unity 全面理解加载和内存管理

    最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别.Resources ...

  9. 基于 CentOS7 的 Kubernetes 集群

    一.环境 相关主机 master 192.168.12.197 minion 192.168.12.198~232 etcd 192.168.12.233~236 相关软件 OS CentOS 7 软 ...

  10. 15套帮助你展示 App 设计的透视屏幕原型素材

    Dribbble 和 Behance 是最好两个展示你的设计作品的地方.现在流行使用透视屏幕来展示应用程序设计效果,尤其是在 Dribbble 上面,有众多高品质的免费资源和设计素材. 这篇文章汇集了 ...