接口
接口
接口概述
为了解决抽象类单继承的局限,Java提供了接口。如果一个类只是由抽象方法和全局常量组成的,那么在这种情况下不会将其定义为一个抽象类,而只会定义为接口。接口就是一种公共规范标准,只要符合规范,大家都可以通用。
接口的使用原则
- 接口必须有子类,但是一个子类可以实现多个接口。(如果子类实现的多个接口中有重名的方法会报错)
- 接口的子类必须重写接口中所有的抽象方法。(如果不想重写全部抽象方法,就定义成抽象类)
- 接口不能实例化(接口没有构造方法),可以利用实现类对象的向上转型进行实例化操作。
interface A{
public static final String MSG = "HelloWorld!";
public abstract void print();
}
对接口而言,其组成部分就是抽象方法和全局常量,所以很多人为了省事不写public abstract和public static final。上式等价于:
interface A{
String MSG = "HelloWorld!";
void print();
}
即使在接口的方法中没有写上public,其最终的访问权限也是public而不是default,覆写接口方法的子类方法的权限不能低于接口的权限,所以子类的方法必须加上public。既然如此,建议在接口中也写上public以防权限出错。
如果一个类既要继承抽象类又要实现接口,那么应该采用先继承后实现接口的顺序完成。一个抽象类可以继承一个抽象类或实现若干个接口,但是一个接口却不能继承抽象类。不过一个接口可以使用extends同时继承多个父接口。
interface A{ //父接口
public abstract void funA();
}
interface B{ //父接口
public abstract void funB();
}
interface C extends A,B{ //接口多继承
public void funC();
}
class X implements C{ //实现C接口要覆写全部抽象方法
public void funA(){}
public void funB }
public void funC(){}
}
下面是一段模拟usb接口的代码:
//定义一个usb接口,供其他设备使用
public interface USB {
public static final String VERSION= "USB 3.1";
public abstract void start();
void stop(); //接口中的方法默认是public abstract,可以略写
}
//定义u盘,实现usb接口的方法
class Flash implements USB{
public void start(){
System.out.println("U盘开始使用");
}
public void stop(){ //接口中的stop()方法没写权限,但要知道其默认是public,所以这里的权限也要是public
System.out.println("U盘停止使用");
}
}
//定义一个打印机,实现usb接口的方法
public class Printer implements USB{
public void start(){
System.out.println("打印机开始工作");
}
public void stop(){
System.out.println("打印机停止工作");
}
}
//定义计算机类
public class Computer {
public void plugin(USB u){ //电脑有插入和拔出usb设备的方法
u.start();
u.stop();
}
}
//一个测试类
public class TestUSB{
public static void main(String[] args) {
Computer c = new Computer();
c.plugin(new Flash());
c.plugin(new Printer());
}
}
程序执行结果:
U盘开始使用
U盘停止使用
打印机开始工作
打印机停止工作
从以上的对象可以看出抽象类的优点比接口更多,但是单继承这一局限完全掩盖了抽象类的优点,所以实际中能用接口就用接口。
接口新特性
随着一些接口被广泛使用,其中的功能可能不够用了,那么就需要添加新的抽象方法。如果一个接口添加了新的抽象方法,那么所有实现此接口的子类都必须覆写此方法,如果一个接口有几十万个子类,那么覆写的任务非常繁重。所以Java引入了新的特性,可以在接口中定义普通方法或静态方法,子类可以根据需要来自行决定是否覆写。
如果要在接口中定义普通方法(默认方法),必须使用public default关键字。如果想要定义静态方法,使用public static关键字。
- 接口的新成员
-
默认方法(Java8):默认方法不是抽象方法,所以不强制被重写,但是可以被重写。重写的时候去掉default关键字。public可以省略,default不能省略
-
静态方法(Java9):定义格式和普通类中的静态方法完全一样。但是接口中的静态方法只能通过接口名调用,不能通过实现类名或者对象名调用。public可以省略,static不能省略
-
私有方法(java9):Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性。
-
格式1
private 返回值类型 方法名(参数列表) { }
private void show() { }
-
格式2
private static 返回值类型 方法名(参数列表) { }
private static void method() { }
-
-
interface IMessage{
public abstract void print(); //抽象方法,必须覆写
public default void fun(){ //Java的新特性允许在接口中定义普通抽象方法,子类可以根据需要来覆写
System.out.println("接口中的普通方法");
}
public static void show(){
System.out.println("接口中的静态方法");
}
}
class MessageImpl implements IMessage{
public void print(){
System.out.println("快上车");
}
}
public class Demo{
public static void main(String[] args) {
MessageImpl m = new MessageImpl();
m.print();
m.fun();
}
}
抽象类和接口的区别
-
成员区别
-
抽象类
变量,常量;有构造方法;有抽象方法,也有非抽象方法
-
接口
常量;抽象方法(新特性也有非抽象方法)
-
-
关系区别
-
类与类
继承,单继承
-
类与接口
实现,可以单实现,也可以多实现
-
接口与接口
继承,单继承,多继承
-
-
设计理念区别
-
抽象类
对类抽象,包括属性、行为
-
接口
对行为抽象,主要是行为
-