接口

接口只是一种约定。——Anders

接口定义了一种规范——多个类共同的公共行为规范。

  • 对于接口的实现者——规定了必须向外提供哪些服务
  • 对于接口的调用者——规定了可以调用哪些服务,如何调用这些服务

生活中经常见到“接口”——

接口的意义:

  • 体现了“规范和实现分离”的设计哲学;
  • 降低了各模块之间的耦合;
  • 可以提高可扩展性和可维护性。

接口的使用

使用interface关键字定义接口:

|-- 接口中的方法默认是抽象方法,只定义不实现(Java 8开始可以有已实现的特殊方法)

|--|-- 类实现接口(implements), 必须实现接口中的所有的未实现方法,否则实现类成为抽象类

|-- 接口中的方法默认是public,可以不写。

|-- 接口不能实例化(不能new)

|-- 接口中的成员变量默认是public static final修饰的,是“常量”。

|-- 一个类可以实现多个接口

interface 接口务虚 {
void 应该做什么();
}
class 实现类务实 implements 接口务虚 {
@Override
public void 应该做什么() {
System.out.println("实现步骤:1.2.3.……");
}
}
public class 接口测试 {
public static void main(String[] args) {
接口务虚 instance;
// instance = new 接口务虚();不能new一个接口,编译不让过
instance = new 实现类务实();
}
}

Java不支持多重继承,但一个类可以实现多个接口。这是Java中接口的一个重要功能。

示例:让郭靖同时继承郭啸天和洪七公是会出错的!

class 郭啸天 {
}
class 洪七公 {
}
class 郭靖 extends 郭啸天 , 洪七公 {
}


使用接口可以实现“多重继承”:

郭靖只能是郭啸天的儿子,

但是郭靖可以同时是很多人的弟子

使用代码定义class 郭啸天,以及多个interface,郭靖可以是它们共同的子类——

class 郭啸天 {
void 忠义() {
System.out.println("忠义");
}
}
interface I江南七怪 {
int COUNT = 7;// 接口内成员变量默认加public static final
void 基本功();
}
interface I哲别 {
void 骑射();
}
interface I洪七公 {
void 降龙十八掌();
}
// ----------------------------------------------
class 郭靖 extends 郭啸天 implements I洪七公, I江南七怪, I哲别 {
@Override
public void 忠义() {
System.out.println("忠义");
}
@Override
public void 降龙十八掌() {
System.out.println("郭靖版 降龙十八掌");
}
@Override
public void 基本功() {
// The final field ... cannot be assigned
// COUNT = 8;
System.out.println("基本功:" + I江南七怪.COUNT);
}
@Override
public void 骑射() {
System.out.println("弯弓射大雕");
}
}
// ----------------------------------------------
public class TestInterface {
public static void main(String[] args) {
郭靖 gj = new 郭靖();
gj.忠义();
gj.基本功();
gj.骑射();
gj.降龙十八掌();
}
}

默认方法、静态方法、私有方法。

JAVA8开始,接口允许定义默认方法

默认方法可以解决接口的升级问题。

比如有接口A,在之前的项目中已经有B、C实现了接口A。现在需要对接口A进行升级,因为接口的方法必须实现,因此B、C也需要新增代码。

有了默认方法,之前的B、C类不用新增代码了。

JAVA8开始,接口允许定义静态方法,也叫类方法,通过接口名直接调用(不能通过对象名调用)

多重继承时,静态方法名可能冲突,因此不准通过对象调用;

实现多接口时,如果默认方法名发生冲突,会出现编译错误,重写方法可以解决冲突。

如果继承的父类和实现的接口中有方法名冲突,可以不重写,默认使用父类里的同名方法。

interface I洪七公 {
void 降龙十八掌();
// Java 8默认方法
default void 打狗棒() {
System.out.println("打狗棒");
}
// Java 8类方法
static void 好吃() {
System.out.println("天生好吃");
}
}
// ----------------------------------------------
class 郭靖 implements I洪七公 {
@Override
public void 降龙十八掌() {
System.out.println("郭靖版 降龙十八掌");
}
}
// ----------------------------------------------
public class TestInterface {
public static void main(String[] args) {
郭靖 gj = new 郭靖();
gj.降龙十八掌();
gj.打狗棒();// 默认方法,不实现也能使用,很像抽象类
I洪七公.好吃();// 类方法,用接口名直接调用
}
}

应用场景

下面程序,模拟了一个Telephone接口,座机(FixedLineTelephone)已经实现了call()方法。

现在接口升级,加入msg()方法用于发短信,新的MobilePhone类需要实现该方法,但是之前的FixedLineTelephone类无需修改。虽然不用实现,但其对象是可以调用新的方法的。

public class 接口新方法 {
public static void main(String[] args) {
FixedLineTelephone p1 = new FixedLineTelephone();
p1.msg();
MobilePhone p2 = new MobilePhone();
p2.msg();
Telephone.mStatic();// 静态方法,通过接口名调用
}
}
interface Telephone {
void call();
default void msg() {// 新加一个默认方法
System.out.println("sendMsg");
}
// 还有静态方法
static void mStatic() {
System.out.println("mStatic");
}
}
// 传统固定电话,只能打电话
class FixedLineTelephone implements Telephone {
@Override
public void call() {
System.out.println(this.getClass() + "call");
}
}
// 新的手机出现,可以发短信了
class MobilePhone implements Telephone {
@Override
public void msg() {
Telephone.super.msg();
System.out.println(this.getClass() + "SendMsg...");
}
@Override
public void call() {
System.out.println(this.getClass() + "call");
}
}

私有方法

JDK9提供的功能,如果多个接口的方法中有重复代码,则可以提取出来放入一个方法中。

这个方法只有接口自己可以调用,实现类不能调用。

|--私有方法有静态和非静态两种

测试(本讲义使用Eclipse,配置JDK12或JDK9比较麻烦,使用如下简单测试办法):

下载JDK12

链接:https://pan.baidu.com/s/12bGX2G_orQq7_OfTZ54eKQ

提取码:fnlg

解压到不是之前JAVA安装的文件夹下(JDK12没有独立的JRE,都放在一起回导致javac和java的-version不一致)

修改JAVA_HOME为JDK12的路径,如:C:\Users\XXX\Downloads\jdk-12

在桌面新建一个文件夹,如J12,里面写java代码如下。

public class TestInterfacePrivateMethod{
public static void main(String[] args) {
A a = new A();
a.defaultMethod_1();
a.defaultMethod_2();
// 外界不可调用私有方法 a.privateMethod();
I.staticMethod_1();
I.staticMethod_2();
// 外界不可调用私有方法 I.privateStaticMethod();
}
} interface I{
private void privateMethod(){
System.out.println("Common");
}
default void defaultMethod_1() {
privateMethod();
System.out.println("defaultMethod_1");
}
default void defaultMethod_2() {
privateMethod();
System.out.println("defaultMethod_2");
}
private static void privateStaticMethod(){
System.out.println("Common Static");
}
static void staticMethod_1() {
privateStaticMethod();
System.out.println("staticMethod_1");
}
static void staticMethod_2() {
privateStaticMethod();
System.out.println("staticMethod_1");
}
} class A implements I{ }

接口继承接口

接口可以继承接口,一个接口可以继承多个其它接口。

interface I1 {
void m1();
}
interface I2 {
void m2();
}
interface I3 extends I1, I2 {
void m3();
}
class 实现类 implements I3 {
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
}
// ---------------------------
public class 接口继承接口 {
}

让接口继承其它接口,可以减少单个接口要做的事情,使得职责划分更清晰,代码更易理解。JDK源码、Java开源框架源码中很多接口继承接口的具体案例,后面都会看到。

最新文章

  1. 转载:TypeScript 简介与《TypeScript 中文入门教程》
  2. 使用dom4j操作XML
  3. Maven 3.3.3 Win10环境下的使用实例(下)
  4. C++小思
  5. 初次体验架设PHP网站
  6. KVC/KVO总结
  7. Oracle函数:求两个数的最小公倍数
  8. 图论(网络流):[SCOI2015]小凸玩矩阵
  9. SCALA中类的继承
  10. Open Wifi SSID Broadcast vulnerability
  11. tangible T4 Editor 2.2.3 for VS2010 / VS2012 / VS2013 Preview
  12. 如何让secureCRT显示Linux的颜色
  13. 智能手机的工业控制应用方案——SimpleWiFi在工业控制领域应用
  14. ZendStudio10.6.1如何安装最新的集成svn小工具?
  15. EFI Shell 命令说明
  16. string的数值转换
  17. rsync技术报告(翻译)
  18. LoadRunner性能测试过程中报Error(-17998):Failed to get [param not passed in call] thread TLS entry.
  19. restful framework 认证源码流程
  20. jupyter-notebook后home页面空白问题

热门文章

  1. jquery里面的一些方法使用
  2. Miniconda 安装 & Pip module 安装 & Shell 脚本调用 Miniconda 虚拟环境手册(实战项目应用)
  3. python给图片添加文字
  4. 解决SBT下载慢,dump project structure from sbt?
  5. PS2018 激活
  6. 排序算法—快速排序(Quick Sort)
  7. XJOI 夏令营501-511NOIP训练18 高三楼
  8. 深入学习OpenCV文档扫描及OCR识别(文档扫描,图像矫正,透视变换,OCR识别)
  9. C语言利用结构体数组实现学生成绩管理系统
  10. java实现科研信息管理系统