Java 面向对象(六)接口
一、接口
- 接口:是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。
- 接口的定义:它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
- 接口的使用:它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
Tips:引用数据类型:数组,类,接口等。
二、定义格式
语法格式:
【权限修饰符】 interface 接口名称 {
接口的成员列表如下:
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}
1、JDK1.7及以前接口成员有两种:静态常量和抽象方法(JDK7+)
全局的静态的常量:接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰(可省略),其实就是接口中的【常量】。
公共的抽象方法:使用publc abstract 关键字修饰,(可以省略)没有方法体。该方法供子类实现使用。
语法格式:
public static final 数据类型 变量名 = 值;
public abstract 返回值类型 方法名称(参数列表);
Demo:
public interface InterFaceName {
public static final long MAX_SPEED = 7900000; //常量
public abstract void method(); //抽象方法
}
Tips:一旦使用final关键字进行修饰,说明不可改变。
注意事项:
a、接口当中的常量,可以省略 public static final,注意:不写也照样是这样。
b、接口当中的常量,必须进行赋值;不能不赋值。
c、接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
2、JDK1.8以后接口有增强两个成员:默认方法和静态方法(JDK8+)
默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。
语法格式:
public default 返回值类型 方法名称(参数列表) {
方法体
}
静态方法:使用public static 修饰,不可省略,供接口直接调用。
Demo:
public interface InterFaceName {
public default void method() {
// 执行语句
}
public static void method2() {
// 执行语句
}
}
扩展:
(1)为什么 Java8 要允许接口中定义静态方法?
因为JDK发展了一段时间后,发现类库中,多了很多的成组的API,如Array和Arrays类,Collection接口和Collections工具类。
一般工具类都是静态方法,这些静态方法,基本上都是为前面这个对应接口服务的。当把这样的静态方法直接挪到接口中定义就好了,减少了这样的工具类的出现。
(2)为什么 Java8 要允许接口中定义默认方法?
因为有的时候,一个接口它的大多数实现类对接口的抽象方法的实现代码是一样的,那样写好几次就非常麻烦。即相当于,默认方法是原来的抽象方法有了一个默认实现。
如果实现类的实现和接口一样,就不需要重写,如果不一样就重写即可。
3、JDK1.9以后增加两个接口成员:私有方法和私有静态方法(JDK9+)
私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。
Demo:
public interface InterFaceName {
private void method() {
// 执行语句
}
}
三、基本的实现
1、实现的概述
类与接口的关系为实现关系,即类实现接口,该类也可以称为接口的实现类,也可以称为接口的子类。
实现的动作似继承,格式相仿,只是关键字不同,实现使用 implements 关键字。
非抽象子类实现接口:
- 必须重写接口中所有的抽象方法。
- 继承了接口的默认方法,即可以直接调用,也可以重写。
实现格式:
class 类名 implements 接口名 {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【可选】
}
2、抽象方法的使用
接口中的抽象方法必须全部实现。
Demo:
// 定义接口:
public interface LiveAble {
// 定义抽象方法
public abstract void eat();
public abstract void sleep();
} // 定义实现类
public class Animal implements LiveAble {
@Override
public void eat() {
System.out.println("吃东西");
}
@Override
public void sleep() {
System.out.println("晚上睡");
}
}
3、默认方法的使用
可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。
(1)继承默认方法
Demo:
// 定义接口
public interface LiveAble {
public default void fly(){
System.out.println("天上飞");
}
} // 定义实现类
public class Animal implements LiveAble {
// 继承,什么都不用写,直接调用
} // 测试类
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用默认方法
a.fly();
}
}
输出结果:
天上飞
(2)重写默认方法
// 定义接口
public interface LiveAble {
public default void fly(){
System.out.println("天上飞");
}
} // 定义实现类
public class Animal implements LiveAble {
@Override
public void fly() {
System.out.println("自由自在的飞");
}
} // 定义测试类
public class InterfaceDemo {
public static void main(String[] args) {
// 创建子类对象
Animal a = new Animal();
// 调用重写方法
a.fly();
}
}
输出结果:
自由自在的飞
4、静态方法的使用
静态与 .class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用。
语法格式:
public static 返回值类型 方法名称(参数列表) {
方法体
}
Demo:
// 定义接口
public interface LiveAble {
public static void run(){
System.out.println("跑起来~~~");
}
} // 定义实现类
public class Animal implements LiveAble {
// 无法重写静态方法
} // 定义测试类
public class InterfaceDemo {
public static void main(String[] args) {
// Animal.run(); // 【错误】无法继承方法,也无法调用
LiveAble.run(); //
}
}
输出结果:
跑起来~~~
5、私有方法的使用
- 私有方法:只有默认方法可以调用;
- 私有静态方法:默认方法和静态方法可以调用;
语法格式:
private 返回值类型 方法名称(参数列表){ 方法体} 普通私有方法
private static 返回值类型 方法名称(参数列表) { 方法体} 静态私有方法
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。
Demo:
public interface LiveAble {
default void func(){
func1();
func2();
}
private void func1(){
System.out.println("跑起来~~~");
}
private void func2(){
System.out.println("跑起来~~~");
}
}
四、接口的多实现(冲突问题)
在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
实现格式:
class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}
1、抽象方法
接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
Demo:
// 定义接口
interface A {
public abstract void showA();
public abstract void show();
}
interface B {
public abstract void showB();
public abstract void show();
} //定义实现类
public class C implements A,B{
@Override
public void showA() {
System.out.println("showA");
}
@Override
public void showB() {
System.out.println("showB");
}
@Override
public void show() {
System.out.println("show");
}
}
2、默认方法
当一个类同时实现了两个甚至更多个接口时,这些个接口中出现了方法签名相同的默认方法时,
必须在这个类中,做出选择:
(1)保留其中一个,放弃另一个;
(2)两者都不用,完全重写一个;
Demo:
interface A{
public default void test(){
System.out.println("aaa");
}
}
interface B{
public default void test(){
System.out.println("bbb");
}
}
class C implements A,B{
//选择一:保留其中一个,放弃另一个
A.super.test(); //保留A接口的实现
B.super.test(); //保留B接口的实现
} class C1 implements A,B{
//选择二:两者都不用,完全重写一个
public void test(){
System.out.println("ccc");
}
}
3、静态方法
接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。
4、优先级的问题
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的方法签名一样的方法,怎么办?
如何选择?
(1)默认选择:编译器默认选择父类中的方法
(2)改选保留接口的
(3)完全自己重写
Demo:
class Father{
public void test(){
System.out.println("ffff");
}
}
interface D{
public default void test(){
System.out.println("dddd");
}
}
class Son1 extends Father implements D{
//选择一:默认选择, 保留父类的
} class Son2 extends Father implements D{
//选择二:改选接口的
public void test() {
D.super.test();
}
} class Son3 extends Father implements D{
// 完全自己重写
public void test() {
System.out.println("ssss");
}
}
五、接口的多继承
一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends 关键字,子接口继承父接口的方法。
如果父接口中的默认方法有重名的,那么子接口需要重写一次。
Demo:
//定义父接口
interface A {
public default void method(){
System.out.println("AAAAA");
}
}
interface B {
public default void method(){
System.out.println("BBBBB");
}
} // 定义子接口
interface D extends A,B{
@Override
public default void method() {
System.out.println("DDDDD");
}
}
Tips:子接口重写默认方法时,default 关键字可以保留;子类重写默认方法时,default 关键字不可以保留。
六、成员特点
- 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用 public static final 修饰。
- 接口中,没有构造方法,不能创建对象。
- 接口中,没有静态代码块。
- 一个类如果直接继承父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
七、接口的特点
1、接口是标准,就是用来被遵守的,即就是用来被实现的,那么要求实现类在实现接口时,必须实现/重写所有的抽象方法,否则这个实现类就得是一个抽象类;
2、接口也是不能直接创建对象的;
3、接口类型的变量与实现类的对象构成多态引用;
4、一个类继承父类时,Java只支持单继承,但是一个类在实现接口时,可以同时实现多个接口;
5、一个类如果同时继承父类,又实现接口时,要求继承在前,实现在后;
【修饰符】 class 实现类 extends 父类 implements 父接口们{}
6、在Java中,接口还可以继承接口;
【权限修饰符】 interface 子接口 extends 父接口们{ }
Java 面向对象(六)接口的更多相关文章
- Java面向对象:接口
Java面向对象之接口 什么是接口:接口是一种规范和标准,他们可以约束类的行为,是一些方法特征的集合 语法: [修饰符] interface 接口名 extends 父接口1,夫接口2....... ...
- JavaSE入门学习21:Java面向对象之接口(interface)(二)
一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.j ...
- JavaSE入门学习20:Java面向对象之接口(interface)(一)
一Java接口 接口(英文:interface)是抽象方法和常量值的集合,在Java编程语言中是一个抽象类型,接口通常以interface来声 明.类是一种详细实现体.而接口定义了某一批类所须要遵守的 ...
- Java 面向对象之接口、多态
01接口的概念 A:接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”. 接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成 ...
- Java面向对象(接口、多态)
面向对象 今日内容介绍 u 接口 u 多态 第1章 接口 1.1 接口概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”. 接口只描述所应该具备的方法,并没有具体实现,具体的 ...
- Java面向对象程序设计--接口和内部类
1.接口的定义: In the Java programming language, an interface is not a class but staff[0] = ...
- java面向对象_接口
java接口 interface,是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并不是类,编写接口的方式和类很相似,但 ...
- Java面向对象之接口interface 入门实例
一.基础概念 (一)接口可以简单的理解为,是一个特殊的抽象类,该抽象类中的方法都是抽象的. 接口中的成员有两种:1.全局常量 2.抽象方法 定义接口用关键字interface,接口中的成员都用固定的修 ...
- Java 面向对象_接口
接口定义 接口就是多个类的公共规范 接口是一种引用数据类型, 最重要的内容是其中的抽象方法 定义格式: public interface MyInterfaceAbstract { // 这是一个抽象 ...
- Java面向对象(二) 接口、多态和泛型
一.接口 二.多态 多态是同一个行为具有多个不同表现形式或形态的能力. 2.1 类型转换 转换方式 隐式 向上转型 对于基本数据类型,存储容量低的可自动向存储容量高的类型转换 对于引用变量,子类可被转 ...
随机推荐
- It’s worth noting值得注意的是
It’s worth noting that in JavaScript applications the Model is often connected via Ajax to a back-en ...
- osg fbx遍历模型节点名称
; k<sg->getNumChildren(); k++) { //转换编 std::string name = vcfbx1.w2m1(vcfbx1.m2w1(sg->getCh ...
- spring boot配置文件、日志配置和代码的多环境配置
一般项目都逃不掉开发.测试和生产这三套环境,如果每次给这三套环境打包都去改配置,累死不说,还一不留心就出差错.倒不如每套环境各给一套配置来的轻松.上代码: 1.通用配置放在application.pr ...
- 不同操作系统上DNS客户端操作区别汇总
结论:windows有DNS缓存,Linux默认无DNS缓存,只能依赖于安装其他软件. 一.不同操作系统的客户端的DNS缓存差别 1.windows 系统中dns 解析器会使用系统的dns缓存来提高d ...
- [AI] 深度数学 - Bayes
数学似宇宙,韭菜只关心其中实用的部分. scikit-learn (sklearn) 官方文档中文版 scikit-learn Machine Learning in Python 一个新颖的onli ...
- 数据结构与算法 Javascript描述
数据结构与算法系列主要记录<数据结构与算法 Javascript描述>学习心得
- iOS-AVPlayer使用
1引入AVFoundation.framework框架 2引入头文件<AVFoundation/AVFoundation.h>,并拖入需要播放的视频文件 代码如下: 自定义播放的View, ...
- 《CNCF × Alibaba云原生技术公开课》知识点自测(三):Kubernetes核心概念
(单选)1.Kubernetes的中文含义是___. A. 船 B.舵手 C.容器平台 D.起重机 (单选) 2.Kubectl是_____. A. 一个与Kubernetes集群进行交互.管 ...
- 使用GDAL进行波段分离
波段分离一般最常用的还是OpenCV,使用OpenCV的split方法可以直接对波段分离,并且效果不错,但是有一个问题是只能处理有限波段的数据,比如波段超过一定的数目就无法完成波段分离工作,或者数据有 ...
- leetcode1130 Minimum Cost Tree From Leaf Values
思路: 区间dp. 实现: class Solution { public: int mctFromLeafValues(vector<int>& arr) { int n = a ...