接口
定义接口
public interface Electronic {
// 常量
String LED = "LED";
// 抽象方法
int getElectricityUse();
// 静态方法
static boolean isEnergyEfficient(String electtronicType) {
return electtronicType.equals(LED);
}
// 默认方法
default void printDescription() {
System.out.println("电子");
}
}
反编译后的字节码:
public interface Electronic
{
public abstract int getElectricityUse();
public static boolean isEnergyEfficient(String electtronicType)
{
return electtronicType.equals("LED");
}
public void printDescription()
{
System.out.println("\u7535\u5B50");
}
public static final String LED = "LED";
}
-
接口中定义的变量会在编译的时候自动加上
public static final
修饰符 -
没有使用
private
、default
或者static
关键字修饰的方法是隐式抽象的,在编译的时候会自动加上public abstract
修饰符。 -
接口不允许直接实例化
-
接口可以是空的,既可以不定义变量,也可以不定义方法。
-
不要在定义接口的时候使用final关键字,否则会报编译错误,因为接口就是为了让子类实现的,而final阻止了这种行为。
-
接口的抽象方法不能是private、protected或者final否则编译器都会报错。
-
接口的变量是隐式
public static final
(常量),所以其值无法改变。
接口作用
- 使某些实现类具有我们想要的功能
- Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的。
- 菱形问题:ClassA和ClassB继承同一个父类,ClassC同时继承了ClassA和ClassB,ClassC的对象在调用ClassA和ClassB中重写的方法时,就不知道该调用ClassA的方法,还是ClassB的方法。
- 实现多态
- 多态是指同一个事件发生在不同的对象上会产生不同的结果
- 多态可以通过继承(
extends
)的关系实现,也可以通过接口的形式实现。
接口的三种设计模式
策略模式
- 针对一组算法,将每一种算法封装到具有共同接口的实现类中,接口的设计者可以在不影响调用者的情况下对算法做出改变。
package test.Interface;
// CS玩家
interface CSPlayer {
// 游戏策略
void strategy();
}
class Cadian implements CSPlayer {
@Override
public void strategy() {
System.out.println("ECO局变形金刚");
}
}
class Jame implements CSPlayer {
@Override
public void strategy() {
System.out.println("保狙,save,save");
}
}
public class Test {
// 参数作为接口
public static void strategy(CSPlayer csPlayer) {
csPlayer.strategy();
}
public static void main(String[] args) {
// 为同一个方法传递不同的对象
strategy(new Cadian());
strategy(new Jame());
}
}
适配器模式
- 针对调用者的需求对原有的接口进行转接。
// CS玩家
interface CSPlayer {
// 指挥
void conduct();
// 突破
void breakthrough();
}
// 抽象类实现接口,并置空方法
abstract class AbstractCSPlayer implements CSPlayer {
public void conduct() {}
public void breakthrough() {}
}
// 新类继承适配器
class Cadian extends AbstractCSPlayer {
@Override
public void conduct() {
System.out.println("指挥队友");
}
}
class Niko extends AbstractCSPlayer {
@Override
public void breakthrough() {
System.out.println("AK突破手");
}
}
- 接口中定义了两个方法,如果类直接实现该接口,需要对两个方法都进行实现。
- 如果只需对其中一个方法进行实现,可以使用一个抽象类作为中间件,即适配器,用这个抽象类实现接口,并对抽象类中的方法置空。此时新类就可以绕过接口去继承抽象类,就可以只对需要的方法进行覆盖。
工厂模式
- 需要啥就用对应的工厂生产
// CS玩家
interface CSPlayer {
void duty();
}
// CSer学院
interface CSerFactory {
CSPlayer createCSer();
}
class Sniper implements CSPlayer {
@Override
public void duty() {
System.out.println("狙击手");
}
}
class Breaker implements CSPlayer {
@Override
public void duty() {
System.out.println("突破手");
}
}
// 狙击手学院
class SniperFactory implements CSerFactory {
@Override
public CSPlayer createCSer() {
return new Sniper();
}
}
// 突破手学院
class BreakerFactory implements CSerFactory {
@Override
public CSPlayer createCSer() {
return new Breaker();
}
}
public class Test {
public static void createCSer(CSerFactory factory){
factory.createCSer().duty();
}
public static void main(String[] args) {
createCSer(new SniperFactory());
createCSer(new BreakerFactory());
}
}
接口和抽象类的区别
- 1、抽象类可以有方法体的方法,但接口没有(Java 8 以前)。
- 2、接口中的成员变量隐式为
static final
,但抽象类不是的。 - 3、一个类可以实现多个接口,但只能继承一个抽象类。
语法层面
- 抽象类可以提供成员方法的实现细节,而接口中只能存在 public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;
- 接口中不能含有静态代码块,而抽象类可以有静态代码块;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
设计层面
-
抽象类是对一种事物的抽象,即对类抽象,继承抽象类的子类和抽象类本身是一种
is-a
的关系。而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。 -
抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。