Java基础(十)接口(interface)
1.接口的概念
在Java中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述。
例如:Array类中的sort方法可以对对象数组进行排序,但要求满足下列前提:对象所属的类必须实现了Comparable接口。
Comparable接口的代码:任何实现了Comparable接口的类都必须包含compareTo方法。
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
接口中的所有方法自动地属于public,因此,在接口中声明方法时,不必提供关键字public。在实现接口时,必须把方法声明为public。
接口没有实例,在接口中可以定义常量,也可以定义简单方法,但是这些方法不能引用实例域。
提供实例域和方法实现的任务应该由实现接口的那个类来完成,因此,可以将接口看成是没有实例域的抽象类。
如果希望用Array类的sort方法对Employee对象数组进行排序,那么Employee类就必须实现Comparable接口。
public class Employee implements Comparable<Employee>
{
...
public int compareTo(Employee other)
{
return Double.compare(salary, other.salary); // 使用静态的compare方法,大于等于小于时分别返回1,-1,0
}
}
为什么不可以直接在Employee类中直接提供compareTo方法而不实现Comparable接口呢:这是因为Java是一种强类型(strongly typed)语言。在调用方法的时候,编译器会检查这个方法是否存在。
Array类中的sort方法中的ComparableTimSort限制了必须有compareTo方法,从而限制了必须实现Comparable接口。
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
2.接口的特性
(1)接口不是类,不能使用new实例化一个接口
(2)尽管不能构造接口的对象,但能声明接口的变量,接口变量必须引用实现了接口的类对象。也可以使用instanceof检查一个对象是否实现了某个特定的接口。
Comparable x;
x = new Employee(...);
if (x instanceOf Comparable) ...
(3)与建立类的继承关系一样,接口也可以被扩展。允许存在多条从具有较高通用性的接口道较高专用性的接口的链。
例如:首先建立一个称为Moveable的接口
package test;
public interface Moveable {
void move(double x, double y);
}
然后建立一个称为Powered的接口,使得这个接口继承Moveable接口:这里注意的是,虽然接口中不能包含实例域,但是却可以包含常量,与接口中的方法自动地被设置成public一样,接口中的域将被自动地设置为public static final。任何实现Powered接口的类都自动地继承了这些常量,并且可在方法中直接引用SPEED_LIMIT这个常量,而不用写成Powered.SPEED_LIMIT这种形式。
package test;
public interface Powered extends Moveable{
double SPEED_LIMIT = 95;
double milesPerGallon();
}
任何实现了Powered 接口的类都必须实现move方法和milesPerGallon方法:
package test;
public class Imp implements Powered{
@Override
public void move(double x, double y) {
// TODO Auto-generated method stub
}
@Override
public double milesPerGallon() {
// TODO Auto-generated method stub
return 0;
}
}
3.接口的好处
前面提到过的Comparable接口也可以用抽象类来表示,接口实现关系也可以用继承来实现,例如:
package test;
public abstract class Comparable<T> {
public abstract int compareTo(T o);
}
Employee类来继承Comparable抽象方法后必须也必须实现compareTo方法:
package test;
public class Employee extends Comparable<Employee>{
@Override
public int compareTo(Employee o) {
// TODO Auto-generated method stub
return 0;
}
}
这看起来似乎没有什么问题,但是,使用抽象类表示通用属性的时候,每个类只能扩展于一个类,即每个类只能单继承。而接口的好处是,每个类可以同时实现很多个接口。接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。
4.在接口中增加静态方法和默认方法
(1)在接口中增加静态方法
Java SE 8 允许在接口中增加静态方法:例如,在Moveable接口中提供了静态方法move,
package test;
public interface Moveable {
static void move(double x, double y) {
System.out.println(x*y);
};
}
任何继承Moveable的类不用去实现move静态方法,并且可以直接调用move方法:
package test;
public class Imp implements Moveable{
public static void main(String[] args) {
Moveable.move(10.0, 10.0); // 打印:100.0
}
}
(2)在接口中增加默认方法
可以为接口中的方法提供一个默认实现,用default修饰符标记这样一个方法,例如,Moveable接口中有两个方法,其中move方法标记为默认方法并且实现:
package test;
public interface Moveable {
int size();
default double move(double x, double y) {
return x*y;
}
}
任何继承Moveable接口的方法,如果没有重写move方法,那么就默认该类具有接口中的默认方法。
package test;
public class Imp implements Moveable{
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
public static void main(String[] args) {
Imp test = new Imp();
System.out.println(test.move(10.0, 10.0)); // 打印:100.0
}
}
如果在继承Moveable接口的方法中重写了默认方法,则以重写的方法为准:
package test;
public class Imp implements Moveable{
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
@Override
public double move(double x, double y) {
// TODO Auto-generated method stub
return x + y;
}
public static void main(String[] args) {
Imp test = new Imp();
System.out.println(test.move(10.0, 10.0)); // 打印:20.0
}
}
默认方法还可以调用任何其他方法,例如,调用同一个接口中的其他方法:
package test;
public interface Moveable {
int size();
default boolean move(double x, double y) {
return size() == 0;
}
}
任何实现Moveable接口的方法都必须实现size方法,并且还拥有move方法的默认实现:
package test;
public class Imp implements Moveable{
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
public static void main(String[] args) {
Imp test = new Imp();
System.out.println(test.move(0.0, 100.0)); // 打印:true
}
}
5.默认方法冲突的解决方法
如果先在一个接口中将一个方法定义为默认方法,然后又在父类或者另一个接口中定义了同样的方法,那么该如何选择:
(1)父类优先。如果父类提供了一个具体方法,同时接口中提供了相同的默认方法,则接口中的默认方法会被忽略。
(2)接口冲突时要重写。如果两个接口都提供一个相同的默认方法,则同时实现这两个接口的类必须重写这个方法。
Java基础(十)接口(interface)的更多相关文章
- Java基础十--接口
Java基础十--接口 一.接口的定义和实例 /* abstract class AbsDemo { abstract void show1(); abstract void show2(); } 8 ...
- Java 基础 面向对象: 接口(interface )概念 以及接口之练习3 -定义一个接口用来实现两个对象的比较并 判断instanceof是否为同类
接口(interface )概念概念笔记 及测试代码: /** 面向对象: 接口(interface ) 是与类并行的一个概念: * 1.接口可以看成一个特殊的抽象类,它是常量与抽象方法的一个集合 * ...
- Java基础-面向接口(interface)编程
Java基础-面向接口(interface)编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的“类 ...
- Java基础十二--多态是成员的特点
Java基础十二--多态是成员的特点 一.特点 1,成员变量. 编译和运行都参考等号的左边. 覆盖只发生在函数上,和变量没关系. Fu f = new Zi();System.out.println( ...
- JavaSE入门学习21:Java面向对象之接口(interface)(二)
一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.j ...
- Java基础10 接口的继承与抽象类
链接地址:http://www.cnblogs.com/vamei/archive/2013/03/31/2982240.html 作者:Vamei 出处:http://www.cnblogs.com ...
- Java基础10 接口的继承与抽象类(转载)
接口继承 接口继承(inheritance)与类继承很类似,就是以被继承的interface为基础,增添新增的接口方法原型.比如,我们以Cup作为原interface: interface Cup{ ...
- 【Java基础】接口和抽象类之间的对比
Java 中的接口和抽象类之间的对比 一.接口 Interface,将其翻译成插座可能就更好理解了.我们通常利用接口来定义实现类的行为,当你将插座上连接笔记本的三角插头拔掉,换成微波炉插上去的时候,你 ...
- java中的接口interface
关于接口 接口描述了实现了它的类拥有什么功能.因为Java是强类型的,所以有些操作必须用接口去约束和标记.接口作为类的能力的证明,它表明了实现了接口的类能做什么. 类似与class,interface ...
- Java基础之接口与抽象类及多态、内部类
final关键字 被其修饰的类,不能被继承. 被其修饰的方法,不能被覆盖. 被其修饰的变量,是一个常量,不能被修改,所以定义时必须初始化(和C++的const类似). 一般有final,会搭配stat ...
随机推荐
- 升级@Scheduled-分布式定时任务
最近我在对项目的定时任务服务升级,希望改造成分布式,原本是利用@Scheduled注解实现,然而它并不支持分布式,如果改成quartz或者Spring Cloud Task,感觉对于自己这个简单的项目 ...
- mybatis - 通用mapper
title: 玩转spring-boot-mybatis date: 2019-03-11 19:36:57 type: "mybatis" categories: mybatis ...
- Gin框架介绍及使用
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
- 列表 元祖 range
1.列表 list 存放一些数据的容器 比如 衣柜 书包 作用:存储一些数据,数据量比较大 可以下标 可以切片 可以步长 和字符串的完全一样 lst = [1,2,3] print(lst) #[1, ...
- git checkout 提示 “error: The following untracked working tree files would be overwritten by checkout” 解决
问题描述 Windows 或者 macOS 操作系统中,文件名是不区分大小写的.对于已经提交到仓库中的文件修改文件名的大小写,然后又用 git rm 命令将老文件从 Git 仓库删除掉,并保存下新的文 ...
- Spring系列(六):Spring事务源码解析
一.事务概述 1.1 什么是事务 事务是一组原子性的SQL查询,或者说是一个独立的工作单元.要么全部执行,要么全部不执行. 1.2 事务的特性(ACID) ①原子性(atomicity) 一个事务必须 ...
- 【CSS】width和height计算
width:calc(100% - 20px); width:-webkit-calc(100% - 20px);//chrome width:-moz-calc(100% - 20px);//fir ...
- SparkStreaming整合Flume的pull报错解决方案
先说下版本情况: Spark 2.4.3 Scala 2.11.12 Flume-1.6.0 Flume配置文件: simple-agent.sources = netcat-source simpl ...
- 网络驱动之net_device结构体
在Linux系统中,网络设备都被抽象为struct net_device结构体.它是网络设备硬件与上层协议之间联系的接口,了解它对编写网络驱动程序非常有益,所以本文将着手简要介绍linux-2.6.3 ...
- js中try、catch、finally的执行规则
首先一个常识就是,在浏览器执行JS脚本过程中,当出现脚本错误,并且你没有手动进行异常捕捉时,他会在浏览器下面出现黄色的叹号,这是正常的,这也不是最重要的,最重要的是,出错行以下的所有JS代码将中停执行 ...