Java核心技术点之接口
1. 为什么使用接口
Java中的接口是一组对需求的描述。接口通过声明接口方法来对外宣布:“要想具有XX功能,就得按我说的做(即实现接口方法)。” 而接口的实现类通过实现相应接口的方法来宣布:“我已经按你说的做了,请赐予我XX功能吧!” 例如,以下是Comparable<T>接口的定义:
public interface Comparable<T> {
int compareTo(T o);
}
Comparable<T>接口中定义了一个compareTo方法,这个方法就是它所描述的需求。也就是说Comparable接口对外宣布:“要想拥有进行比较的功能,得按我说的做(实现compareTo方法)。” 若我们想调用Arrays.sort方法对一个People对象数组进行比较,那么People对象必须是”可比较的”,即People类需要实现Comparable<T>接口。接口的实现类需要实现接口中定义的方法。People类通过实现Comparable<T>接口的方法来宣称:”我已经按你说的做啦,请让我变为可比较的吧!“ 也就是说,接口描述了一组需求,而实现一个接口的类就需要实现这个接口所描述的需求。比如我们想要People类对象是可比较的,我们可以这样:
public class People implements Comparable<People> {
...
public int compareTo(People p) {
//定义具体的比较标准
}
...
}
实际上,Arrays.sort方法之所以要求它所比较的对象需实现了Comparable接口,是因为它在比较对象时调用的对象的compareTo方法(因为它不知道评价一个对象大小的标准,这个标准是由我们来定的)。那么,我们为什么不直接在People类中定义一个compareTo实例方法来定义People对象的比较标准,而是要去实现一个Comparable<T>接口呢?让我们举例来说明以下,假如我们调用了以下代码来对People对象数组peoples进行比较:
Arrays.sort(peoples);
在sort方法内部,实际上调用了类似下面这样的代码来比较People对象:
if (peoples[i].compareTo(peoples[j]) > 0) {
//若为true说明peoples[i] 大于peoples[j]
}
也就是说Arrays.sort方法内部调用了People对象的compareTo方法,那么编译器如何知道People类中确实定义了一个方法呢?若People类没有实现Comparable接口,编译器就只有检查这个类是否实现了这个方法,这样做无疑会增大开销,若接口中的方法不只一个,开销就更大了。而且需要比较的对象可能不只一个,假如后面又有Date对象、Job对象需要我们比较呢?如果每次调用相应对象的compareTo方法都要去检查一下它究竟实现了这个方法没有,将无形中增加很多本不必要的开销。
反过来,我们看看引入接口的好处。People类头部的"implements Comparable<People>“就像是在告诉编译器”我是可比较的,可以直接调用我的compareTo方法而不用检查我有没有这个方法“。这样一来,所有可比较的对象只要实现Comparable<T>接口,编译器就能够知道它一定定义了compareTo方法。一个接口实际上是描述了一种规范,它只说明了这个接口需要实现什么需求,而没有强制规定这个需求如何实现。就像之前我们提到的Comparable<T>接口,需要比较大小的对象不只People对象一个,既然大家都需要比较大小,那索性就来个规定,所有想比较大小的对象的类都实现Compareble<T>接口,统一规定一下可比较的对象究竟该满足什么需求(这里的需求就是compareTo方法)。
2. 接口的特性
Comparable<People> p = new People(...);
if (p instanceof Comparable) {
...
}
我们也可以”继承“一个接口:
public interface InA extends InB {
...
}
接口还有一个很有用的特性就是一个类可以实现多个接口。其实以上提到的接口特性只要”接口只是一种规范”这个本质来看就很好理解:比如接口中不能实例化、不能含有实例变量,就是因为接口不同于类那样是一个“蓝图”,接口更像一个“标签”。
3.接口与抽象类的比较
4. 接口与回调(callback)
回调(callback)是一种常见的设计模式,利用这种模式,我们可以指出在某个事件发生时应该采取什么动作。比如,Java类库中有个Timer类,可以使通过它在过了指定的时间后发出通知,就像一个闹钟一样。初始化Time类时,需要指定一个时间和到达这个时间后要执行的动作。在这里,告诉Timer要执行的动作就是通过传递给它一个对象,然后到达指定时间后,Timer会调用这个对象的方法。Timer要求我们传递给它的对象需要实现ActionListener接口,这个接口的定义如下:
public interface ActionListener {
public void actionPerformed(ActionEvent event);
}
我们传递给Time构造器的对象必然定义了actionPerformed方法,我们可以在这个方法中定义我们在定时间隔到达后需要执行的动作。请看以下代码:
public class TimerTest {
public static void main(String[] args) {
ActionListener listener = new TimePrinter();
Timer t = new Timer(10000, listener);
t.start();
System.exit(0);
}
}
class TimePrinter implements ActionListener {
public void actionPerformed(ActionEvent event) {
Date now = new Date();
System.out.println("The time is " + now);
}
}
在以上代码中,会每隔10秒调用一次TimerPrinter中的actionPerformed方法,获取并输出一次当前时间。actionPerformed方法就是回调方法,在回调模式中,通常都是一个类(TimePrinter)实现一个接口(ActionListener),然后另一个类(Timer)的对象通过持有实现该接口的类对象引用(listener)来调用相应的回调方法。
5.参考资料
Java核心技术点之接口的更多相关文章
- Java核心技术卷一基础知识-第6章-接口与内部类-读书笔记
第6章 接口与内部类 本章内容: * 接口 * 对象克隆 * 接口与回调 * 内部类 * 代理 接口技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现(implement)一 ...
- Java核心技术点之泛型
1. Why ——引入泛型机制的原因 假如我们想要实现一个String数组,并且要求它可以动态改变大小,这时我们都会想到用ArrayList来聚合String对象.然而,过了一阵,我们想要实现一个大小 ...
- Java核心技术点之集合框架
1. 概述 Java集合框架由Java类库的一系列接口.抽象类以及具体实现类组成.我们这里所说的集合就是把一组对象组织到一起,然后再根据不同的需求操纵这些数据.集合类型就是容纳这些对象的一个容 ...
- Java核心技术点之内部类
1. 为什么要使用内部类 内部类就是定义在一个类内部的类,那么为什么要使用内部类呢?主要原因有以下几点:第一,内部类中定义的方法能访问到它所在外部类的私有属性及方法:第二,外部类无法实现对同一 ...
- Java核心技术点之动态代理
本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理.由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一.概述 1. 什么是代 ...
- java核心技术学习笔记之一程序设计概述
Java 核心技术之一程序设计概述 一. Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...
- java核心技术之流与文件
InputStream和OutputStream构成了输入/输出类层次结构的基础.用于按字节进行读写.而与之处在同一等级的Reader/Writer同样作为抽象类定义了用于对字符进行读取的类层次结构, ...
- Java命名和目录接口——JNDI
JNDI即Java命名和目录接口(JavaNaming and Directory Interface),它属于J2EE规范范畴,是J2EE的核心技术之一,提供了一组接口.类和关于命名空间的概念.JD ...
- Java核心技术第五章——1.类、超类、子类(2)
继上一篇Java核心技术第五章——1.类.超类.子类(1) 6.重载解析 假如调用ClassName.Method(args) 1.编译器列出类ClassName所有名为Method的方法. 2.编译 ...
随机推荐
- python学习——常用模块
在学习常用模块时我们应该知道模块和包是什么,关于模块和包会单独写一篇随笔,下面先来了解有关在python中的几个常用模块. 一.什么是模块 常见的场景:一个模块就是一个包含了python定义和声明的文 ...
- Django模板语言与视图(view)
常用语法 {{ }}和{% %} 变量相关的用{{}} , 逻辑相关的用{% %} 变量 在Django的模板语言中按此语法使用:{{ 变量名 }}. 当模版引擎遇到一个变量,它将计算这个变量,然后 ...
- (数据科学学习手札41)folium基础内容介绍
一.简介 folium是js上著名的地理信息可视化库leaflet.js为Python提供的接口,通过它,我们可以通过在Python端编写代码操纵数据,来调用leaflet的相关功能,基于内建的osm ...
- java基础之while语句的练习
计算1-100,7的倍数的数的总和 代码如下: public class Demo1 { public static void main(String[] args) { int num=1; int ...
- 优步UBER司机全国各地奖励政策汇总 (3月7日-3月13日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 成都Uber优步司机奖励政策(4月2、3日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- ubuntu网卡
查看网卡类型 http://blog.csdn.net/eddy_liu/article/details/6578819 qii@ubuntu:~$ lspci | grep -i net 03:0 ...
- zookeeper的图形化展示
1.ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供 ...
- Odd CSS syntax. [class^='icon-'], [class*=' icon-']
原文: https://stackoverflow.com/questions/20322740/odd-css-syntax-class-icon-class-icon I am going thr ...
- Qt-Qml-隐藏标题栏-程序依附任务栏
最近换工作,直接欢动qml这边来了,以后可能会有更多关于qml的文章 今天第一个,qml下面怎么隐藏标题栏 第一种方法是在使用QQuickView加载qml文件的话,这里就可以使用QQuickView ...