4.3Java 接口

《编程导论(Java)·4.3Java接口》

随着Java8的出现,本节面临尴尬的局面。这里首先按照原有的Java语言设计思路(Java8之前)介绍Java接口,再看看Java8对Java语言设计思路的破坏。


强大而有用的机制

【p142:类甚至是abstract class,理论上都包含实现,因此类是接口和实现的综合体,如[3.1.3 接口与实现分离]所述。如果说抽象方法是纯粹的接口、脱离了实现的接口,那么Java接口就是这些纯粹的接口组成的数据抽象。Java接口只能够拥有抽象方法,它不涉及任何实现,也不能创建其对象(这一点和抽象类一致)。因此,Java接口纯粹是契约的集合,是一种程序设计的表达方式。从数据抽象的角度看,能够在不定义class的同时又可以定义type,将是程序设计中强大而有用的机制。】

按照接口与实现分离原则,用户仅需要了解接口。每一个抽象方法都是一个纯粹的接口,它不得不与实现相分离。抽象方法是功能抽象的最高形式。在抽象方法的基础上,有了abstract class——类层次的元素,它理论上是接口和实现的综合体;而Java接口纯粹是契约的集合,它以跨越类层次的方式定义type,是一种程序设计中强大而有用的机制。

【p144

接口具有下述性质。

(1)接口不提供代码重用性。接口并不能使你获得代码继承的好处,它没有代码重用能力。接口的意义在于获得程序设计上的高度可维护性。

(2)接口能够通过多继承进行扩展父接口。Java支持接口多继承。interface A extends B, C, D{}

(3)接口不能升级。定义接口时要考虑周全,因为接口有个十分尴尬的限制:如果定义了接口,将接口送给客户程序员使用,这时定义的接口就不能修改。因为在接口中添加一个方法,会导致老版本接口的所有实现类的中断。为了达到在接口中增加一个方法的目的,只能派生/创建一个新的接口。(所以,Java接口天然符合OCP/开放封闭原则)】

常量接口问题

在一个Java接口中定义一系列静态常量,其它类通过import static语句引入和使用这些常量,这一“常量接口模式”在《Effective Java(第2版)·第19条》中被批评——常量接口模式是对接口的不良使用。

当然,《Effective Java(第2版)·第19条》的理由有些牵强。为了使用常量接口A,只有最愚蠢的人会让自己的类B implements A,而他提供的方案——不可实例化的工具类,通过类名访问常量(包括使用static import),与使用常量接口模式,并没有本质的区别。

在我们所使用的常量不会发生变化的情况下,使用常量接口和不可实例化的工具类事实上都可以;

在我们所使用的常量会发生变化——比如公司名为Sun后来改为oracle,所有使用了其常量的类都需要重新编译。因为命名常量不需要占用本类的内存空间。它可能保存在客户类型的常量池中或方法的字节码中(p40,表1-2).

package semantics;
/**
 * 常量接口/不可实例化的工具类
*/
public class Const{
    public static final int X = 100;
    private Const() {    }
}

在另外的包中有用户类

package semantics.staticDemo;
import static semantics.Const.*;
public class UseConst{
    static void test(){
        System.out.println("semantics.Const.X is "+X);
    }
}

两者都编译后,执行UseConst.test,                                                   输出为:semantics.Const.X is 100

将Const的X变化为200,编译Const后,直接执行UseConst.test,输出为:semantics.Const.X is 100

重新编译UseConst,再执行UseConst.test,                                     输出为:semantics.Const.X is 200

虽然我也认为:常量接口模式是对接口的不良使用。但是原因不是技术上的,而是感觉上的。既然可以使用不可实例化的工具类——抽象类或者仅有private构造器的类,那么就不要使用常量接口,让Java接口作为纯粹的契约的集合

所以,【语法上,Java接口(interface)是定义abstract方法和静态命名常量的Java程序单元。因为接口中命名常量的应用非常有限,通常的讨论中一般忽略它。】

Java8的破坏

Java8(通过默认方法)抹杀了Java接口与抽象类的本质区别。接口的性质1和3,不再成立;而“接口不能升级”正是Java8需要突破的地方。

《4.3.2 多重继承问题3. 问题仍然存在》

Java8在Java接口方面的唯一好处,反证了“接口能够多继承,并不意味着Java是为了解决多继承问题而引入接口机制,也不意味着接口机制能够解决程序设计对多继承的需求”。

【为什么Java接口能够避免多继承的复杂性,关键在于它仅仅包含abstract方法。】

【p147 从设计的角度看,Java接口放弃了多继承的内在/固有目标,而显得是一个权宜之计。】

.....................

返回 导航

4.3Java 接口,布布扣,bubuko.com

时间: 2024-10-11 22:02:06

4.3Java 接口的相关文章

纠结的默认方法

[编程导论(Java)·4.3Java接口] 在[0.3.1 Java简介]中,有这么一段话:"请注意:Java并非作为教学语言设计的.世界各地的大学在讲授Java的过程中均遇到一些教学上的困难(如Java语言和API的快速升级),这些困难是计算机科学教育中一般性的挑战." Java8中引入的默认方法,充分展示了Java平台概念的一致性与JDK向前兼容之间的矛盾,而且以牺牲概念的一致性而满足JDK向前兼容. 其后果是原有的Java语言设计思路被破坏,Java接口与抽象类的区别被抹杀.

微信公众号可通过现金红包接口发放微信支付现金红包(附开发教程)

农历新年将至,支付宝红包打了一仗,微信在朋友圈屏蔽了它的分享,但单防守还不行,进攻才是最好的防守.昨日,微信支付现金红包接口正式开放,只需开通微信支付,即可接入现金红包.微信公众号也可以发放现金红包了! 通过现金红包接口,公众号开发者可以策划相关运营活动,向用户发放微信支付现金红包,更好的达到品牌推广及回馈用户的效果. 1.商户调用接口时,通过指定发送对象以及发送金额的方式发放红包,这样的方式,允许商户灵活的应用于各种各样丰富的活动场景 2.领取到红包后,用户的资金直接进入微信零钱,避免繁复的领

.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)

阅读目录: 1.环路执行对象模型.碎片化执行模型(假递归式调用) 2.N层对象执行模型(纵横向对比链式扩展方法) 3.LINQ查询表达式和链式查询方法其实都是空壳子 4.详细的对象结构图(对象的执行原理) 5.IQueryable<T>与IQueryProvider一对一的关系能否改成一对多的关系 6.完整的自定义查询 1]. 环路执行对象模型.碎片化执行模型(假递归式调用) 这个主题扯的可能有点远,但是它关系着整个LINQ框架的设计结构,至少在我还没有搞懂LINQ的本意之前,在我脑海里一直频

.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)

阅读目录: 1.开篇介绍 2.扩展Linq to Object (应用框架具有查询功能) 2.1.通过添加IEnumerable<T>对象的扩展方法 2.2.通过继承IEnumerable<T>接口 2.3.详细的对象结构图 3.实现IQueryable<T> .IQueryProvider接口 3.1.延迟加载IEnumertor<T>对象(提高系统性能) 3.2.扩展方法的扩展对象之奥秘(this IQueryable<TSource> so

Python:hashlib加密模块,flask模块写登录接口

hashlib模块 主要用于加密相关的操作,(比如说加密字符串)在python3的版本里,代替了md5和sha模块,主要提供 sha1, sha224, sha256, sha384, sha512 ,md5 这些加密方式 import  hashlib m = hashlib.md5()   #用md5加密的方式(md5加密后无法解密),创建一个md5的对象 m.update(b"Hello")  #b代表二进制字节bytes,把字符串hello转成字节,然后加密:用b给一个变量转换

谈谈-Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

微信jssdk批量添加卡券接口

1)首先是官方接口文档: 1.批量添加卡券接口:https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.08619731531288366&token=&lang=zh_CN#wxkq3 : 2.卡券扩展字段cardExt说明:https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=0.08619731531288366&t

微信公众号调用接口返回码

返回码 说明 -1 系统繁忙,此时请开发者稍候再试 0 请求成功 40001 获取access_token时AppSecret错误,或者access_token无效.请开发者认真比对AppSecret的正确性,或查看是否正在为恰当的公众号调用接口 40002 不合法的凭证类型 40003 不合法的OpenID,请开发者确认OpenID(该用户)是否已关注公众号,或是否是其他公众号的OpenID 40004 不合法的媒体文件类型 40005 不合法的文件类型 40006 不合法的文件大小 4000

MVC下微信企业号网页应用开发调用JSSDK接口不成功问题

在MVC下进行企业微信里的网页应用开发,前台页面中为了调用图像接口,使用了JSSDK.按照官方文档进行了正确配置. 现象:WEB开发工具调试一切正常,但从手机企业微信应用进入页面后接口调用无效(这个页面是从一级页面链接过来的),开了调试模式后,显示config:ok.说明配置无误.经过反复检查,终于发现问题所在. 原因:在一级页面(http://xx.xxx.xxx/main/index)中的链接是使用htmlhelper来写的,即@Html.ActionLink("测试接口",&qu