接口概述
一方面,有时必须从几个类中派生一个子类,继承他们所有的属性和方法。但是Java不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类抽取一些共同的行为特征,而他们之间又没有is-a的关系,仅仅是具有相同的行为特征而已。例如鼠标,键盘,摄像头都属于输入设备,使用USB连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。继承是一个是不是的关系,接口是一个能不能的关系。
接口的本质是契约,标准,规范,就像我们的法律一样。指定好后大家都要遵守。
举例
比如飞机、子弹、风筝、热气球都可以飞,但是子弹有攻击性。
我可以定义一个可以飞的接口和一个具有攻击性的接口。
飞机、风筝和热气球实现可以飞的接口,子弹实现这两个接口。
/**
* 接口的使用:
* 1.接口使用interface来定义
* 2.Java中,接口和类是并列的两个结构
* 3.如何定义接口:定义接口中的成员
* 4.JDK7以前只能定义常量和抽象方法
* 5.JDK8以后除了定义常量和抽象方法外还有静态方法和默认方法
* 6.接口中不能定义构造器
* 7.Java开发中,一般让类实现(implements)接口
* 8.如果实现类重写了接口的所有抽象方法,就可以实例化
* 9.Java类可以实现多个接口,弥补了Java无法多重继承
* 10.接口与接口之间可以多继承
* 11.接口的实现体现了多态性
* 12.接口就是一种规范
*
*/
public class InterfaceTest {
public static void main(String[] args) {
// 全局变量可以直接调用
System.out.println(Flyable.MAX_SPEED);
// 实例化实现类Plane
Plane plane = new Plane();
plane.fly();
plane.stop();
// 实例化实现类Bullt
Bullet bullet = new Bullet();
bullet.fly();
bullet.stop();
bullet.att();
}
}
// 飞接口
interface Flyable{
// 全局常量
public static final int MAX_SPEED = 7900;
int MIN_SPEED = 1;
// 抽象方法
public abstract void fly();
void stop();
}
// 攻击性接口
interface Attackable{
// 抽象方法
public abstract void att();
}
/**
* 飞机实现类
*/
class Plane implements Flyable{
@Override
public void fly(){
System.out.println("使用引擎起飞");
}
@Override
public void stop(){
System.out.println("驾驶员减速降落");
}
}
/**
* 风筝实现类
*/
class Kite implements Flyable{
@Override
public void fly(){
System.out.println("乘风而飞");
}
@Override
public void stop(){
System.out.println("收线降落");
}
}
/**
* 子弹实现类
*/
class Bullet implements Flyable,Attackable{
@Override
public void fly(){
System.out.println("biubiubiu");
}
@Override
public void stop(){
System.out.println("papapa");
}
@Override
public void att(){
System.out.println("攻击性");
}
}
// 接口的多继承
interface A extends Flyable,Attackable{
}
如何体会接口是一种规范
我们定义一个电脑类,想要和电脑发生信息交互,就必须通过USB接口。
然后我们定义连接USB接口的规范是什么,首先要建立连接,传输完数据后要断开连接。
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
Flash flash = new Flash();
com.transferData(flash);
}
}
// 定义一个电脑类
class Computer{
public void transferData(USB usb){
usb.start();
System.out.println("传输数据");
usb.stop();
}
}
// 这是一个USB接口
interface USB{
void start();
void stop();
}
// 我们可以接入U盘
class Flash implements USB{
@Override
public void start(){
System.out.println("U盘开始工作");
}
@Override
public void stop(){
System.out.println("U盘结束工作");
}
}
// 我们可以接入打印机
class Printer implements USB{
@Override
public void start(){
System.out.println("打印机开始工作");
}
@Override
public void stop(){
System.out.println("打印机结束工作");
}
}
接口匿名实现类
public class USBTest {
public static void main(String[] args) {
// 非匿名实现类
Computer com = new Computer();
Flash flash = new Flash();
com.transferData(flash);
// 匿名实现类
com.transferData(new Printer());
// 创建了接口的匿名实现类的非匿名对象
USB phone = new USB(){
@Override
public void stop() {
System.out.println("手机开始工作");
}
@Override
public void start() {
System.out.println("手机停止工作");
}
};
com.transferData(phone);
// 创建了接口的匿名实现类的匿名对象
com.transferData(new USB(){
@Override
public void stop() {
System.out.println("MP3开始工作");
}
@Override
public void start() {
System.out.println("MP3停止工作");
}
});
}
}
// 定义一个电脑类
class Computer{
public void transferData(USB usb){
usb.start();
System.out.println("传输数据");
usb.stop();
}
}
// 这是一个USB接口
interface USB{
void start();
void stop();
}
// 我们可以接入U盘
class Flash implements USB{
@Override
public void start(){
System.out.println("U盘开始工作");
}
@Override
public void stop(){
System.out.println("U盘结束工作");
}
}
// 我们可以接入打印机
class Printer implements USB{
@Override
public void start(){
System.out.println("打印机开始工作");
}
@Override
public void stop(){
System.out.println("打印机结束工作");
}
}
JDK8中的接口新特性
Java8中,你可以添加静态方法和默认方法。
静态方法:使用static关键字修饰。可以通过接口直接调用静态方法,并执行方法体。
默认方法:默认方法使用default关键字修饰。可以通过实现类对象来调用。
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
s.method2();
s.method3();
// 静态方法只能通过接口直接调用
CompareA.method1();
}
}
class SubClass implements CompareA{
}
----------
public interface CompareA {
// 魔幻现实主义,接口里面有方法了
public static void method1(){
System.out.println("CompareA:北京");
}
// 上面的是静态方法,下面的是默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
default void method3(){
System.out.println("CompareA:广州");
}
}
默认对象也可以重写。
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
s.method2();
s.method3();
// 静态方法只能通过接口直接调用
CompareA.method1();
}
}
class SubClass implements CompareA{
public void method2(){
System.out.println("subclass:上海");
}
}
----------
public interface CompareA {
// 魔幻现实主义,接口里面有方法了
public static void method1(){
System.out.println("CompareA:北京");
}
// 上面的是静态方法,下面的是默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
default void method3(){
System.out.println("CompareA:广州");
}
}
问题:如果SubClass继承于父类SuperClass,SuperClass也有一个方法method3,那么SubClass的method3方法输出什么呢?
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
s.method2();
s.method3(); // 执行父类的method3
// 静态方法只能通过接口直接调用
CompareA.method1();
}
}
class SubClass extends SuperClass implements CompareA{
public void method2(){
System.out.println("subclass:上海");
}
}
----------
public class SuperClass {
public void method3(){
System.out.println("SupClass:广州");
}
}
----------
public interface CompareA {
// 魔幻现实主义,接口里面有方法了
public static void method1(){
System.out.println("CompareA:北京");
}
// 上面的是静态方法,下面的是默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
default void method3(){
System.out.println("CompareA:广州");
}
}
总结一下就是方法先找类本身的,再找父类的,再找接口的。
如果实现两个接口,然后两个接口的默认方法冲突了,那么就会报错。如果想要使用该方法,在实现类中必须要重写该方法。