接口定义:
官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
我的解释:接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法。(JDK1.8之前可以这样理解)
接口的特点:
1.就像一个类一样,一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)。
2.如果一个类实现了一个接口中要求的所有的方法,然而没有提供方法体而仅仅只有方法标识,那么这个类一定是一个抽象类。(必须记住:抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类)
3.接口被用来描述一种抽象。
4.因为Java不像C++一样支持多继承,所以Java可以通过实现接口来弥补这个局限。
5.接口被用来实现抽象,而抽象类也被用来实现抽象,但是抽象类内部可能包含非final的变量,而在接口中存在的变量默认是final,public,static的。
6.一个类可以实现不止一个接口。
7.一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。
8.一个类如果要实现某个接口的话,那么它必须要实现这个接口中的所有方法。
9.接口中所有的方法都是抽象的和public的,所有的属性都是public,static,final的。
10.接口用来弥补类无法实现多继承的局限。
11.接口也可以用来实现解耦,接口被不同的类实现,灵活组合
接口的声明:
声明一个接口,我们使用interface这个关键字,在接口中的所有方法都必须只声明方法标识,而不要去声明具体的方法体,因为具体的方法体的实现是由继承该接口的类来去实现的,因此,接口并不用管具体的实现。接口中的属性默认为Public Static Final.一个类实现这个接口必须实现这个接口中定义的所有的抽象方法。
接口与抽象类的区别:
接口与抽象类
接口 | 抽象类 |
不考虑java8中default方法的情况下,接口中是没有实现代码的实现 | 抽象类中可以有普通成员方法 ,并且可以定义变量 |
接口中的方法修饰符号 只能是public | 抽象类中的抽象方法可以有public ,protected ,default |
接口中没有构造方法 | 可以有构造方法 |
选择:
1、当我们需要一组规范的方法的时候,我们就可以用接口,在具体的业务中,来对接口进行实现,能达到以不变应对万变,多变的需求的情况我们只需要改变对应的实现类 。
2、如果多个实现类中有者相同可以复用的代码 这个时候就可以在实现类和接口之间,添加一个抽象类,把公共的代码抽出在抽象类中。然后要求不同实现过程的 子类可以重写抽象类中的方法,来完成各自的业务。
接口与回调
回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定事件发生时应该采取的动作。如在java.swing包中有一个Timer类,可以使用它在给定的事件间隔时发出通告。
如程序中有一个时钟,请求每秒钟获得一个通告,以便更新时钟的画面。定时器需要直到调用哪一个方法,并要求传递的对象实现了java.awt.ActionListner接口.
public interface ActionListener extends EventListener {
//回调方法,ActionEvent提供了事件的相关信息
public void actionPerformed(ActionEvent e);
}
当到达指定时间间隔时,定时器就调用actionPerformed方法。
案例:每10秒钟打印一条信息”At the tone,the time is ...“
package edu.uestc.avatar.beep;
import javax.swing.JOptionPane;
import javax.swing.Timer;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDateTime;
public class BeepDemo {
public static void main(String[] args) {
/**
* 创建一个定时器
* 每10000毫秒触发定时器,定时器就会调用该事件里的回调方法
*/
Timer timer = new Timer(1000, new BeepActionListner());
//启动定时器
timer.start();
JOptionPane.showMessageDialog(null, "退出定时器");
System.exit(0);
}
}
class BeepActionListner implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("At the tone,the time is " + LocalDateTime.now());
Toolkit.getDefaultToolkit().beep();
}
}
Java8改进的接口
在jdk1.8以前,接口里只能定义常量(public static final)和抽象方法(public abstract),试想,假设1万个类实现了一个接口,这时候对接口进行了升级,按照jdk1.7的规则,加方法的话只能加
抽象方法,当加完抽象方法之后1万个类瞬间编译报错。因为必须要重写抽象方法,在jdk1.8提出接口更新。
有的时候我们希望1万个类如果有类想升级那么重写,有类的不想升级就别重写了。这时候默认方法方法就来了,用default修饰,默认方法可提供方法实现,而实现该接口的类可以不用实现默认方法
接口中可以定义静态方法,让接口具备了功能, 让接口来调用(通过接口名.方法名调用)
接口中有且仅有一个抽象方法的接口即为函数式接口,可以使用@FunctionalInterface检查定义的接口是否是一个函数式接口。函数式接口可以采用lambda表达式。