Java 介面 (Interface)
介面定義一組方法規格,類別可以實作介面來保證具有特定的行為。
基本語法
使用 interface 定義,implements 實作:
// 定義介面
public interface Drawable {
void draw();
}
// 實作介面
public class Circle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
介面的特點
- 方法預設是
public abstract - 變數預設是
public static final(常數) - 不能有建構子
- 類別可以實作多個介面
public interface Animal {
// 常數(自動加上 public static final)
int MAX_AGE = 100;
// 抽象方法(自動加上 public abstract)
void eat();
void sleep();
}
實作多個介面
public interface Swimmable {
void swim();
}
public interface Flyable {
void fly();
}
// 實作多個介面
public class Duck implements Swimmable, Flyable {
@Override
public void swim() {
System.out.println("Duck is swimming");
}
@Override
public void fly() {
System.out.println("Duck is flying");
}
}
繼承類別同時實作介面
public class Animal {
protected String name;
}
public interface Pet {
void play();
}
// 先 extends 再 implements
public class Dog extends Animal implements Pet {
@Override
public void play() {
System.out.println(name + " is playing");
}
}
default 方法 (Java 8+)
介面可以有預設實作:
public interface Vehicle {
void start();
// default 方法
default void stop() {
System.out.println("Vehicle stopped");
}
}
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
// stop() 使用預設實作
}
static 方法 (Java 8+)
public interface StringUtils {
static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
}
// 使用介面名稱呼叫
boolean empty = StringUtils.isEmpty(""); // true
private 方法 (Java 9+)
介面內部使用的私有方法:
public interface Calculator {
default int addAndDouble(int a, int b) {
return doubleIt(a + b);
}
default int subtractAndDouble(int a, int b) {
return doubleIt(a - b);
}
// 私有方法,供 default 方法使用
private int doubleIt(int n) {
return n * 2;
}
}
介面繼承
介面可以繼承其他介面:
public interface Animal {
void eat();
}
public interface Pet extends Animal {
void play();
}
// 實作 Pet 需要實作兩個方法
public class Dog implements Pet {
@Override
public void eat() { }
@Override
public void play() { }
}
常用介面
Comparable
public class Student implements Comparable<Student> {
private String name;
private int score;
@Override
public int compareTo(Student other) {
return this.score - other.score;
}
}
// 可以排序
List<Student> students = new ArrayList<>();
Collections.sort(students);
Cloneable
public class Person implements Cloneable {
private String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
函數式介面 (Java 8+)
只有一個抽象方法的介面,可以用 Lambda:
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}
// 使用 Lambda
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
System.out.println(add.calculate(5, 3)); // 8
System.out.println(multiply.calculate(5, 3)); // 15
實際應用
策略模式
public interface PaymentStrategy {
void pay(double amount);
}
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("信用卡支付 $" + amount);
}
}
public class PayPalPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("PayPal 支付 $" + amount);
}
}
// 使用
public void checkout(PaymentStrategy strategy, double amount) {
strategy.pay(amount);
}
回呼 (Callback)
public interface OnClickListener {
void onClick();
}
public class Button {
private OnClickListener listener;
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick();
}
}
}
// 使用
button.setOnClickListener(() -> System.out.println("按鈕被點擊"));
介面 vs 抽象類別
更詳細的比較請參考 Java 抽象類別 vs 介面。