跳到主要内容

Java 接口

接口(Interface)是 Java 中定义抽象行为的重要类型。本章将详细介绍接口的概念、使用以及 Java 8 后的新特性。

接口基础

什么是接口?

接口是一种抽象类型,它定义了一组方法签名,但不提供具体实现。类通过实现接口来提供具体行为。

定义接口

// 定义接口
interface Drawable {
// 抽象方法 - 没有方法体
void draw();

// 常量(默认是 public static final)
int MAX_SIZE = 100;
}

实现接口

// 实现接口
class Circle implements Drawable {
private int radius;

public Circle(int radius) {
this.radius = radius;
}

// 必须实现抽象方法
@Override
public void draw() {
System.out.println("绘制圆形,半径:" + radius);
}
}

// 使用
Drawable drawable = new Circle(10);
drawable.draw();

多个接口实现

一个类可以实现多个接口:

interface Drawable {
void draw();
}

interface Movable {
void move();
}

// 实现多个接口
class Robot implements Drawable, Movable {
@Override
public void draw() {
System.out.println("绘制机器人");
}

@Override
public void move() {
System.out.println("机器人移动");
}
}

接口特性

接口成员

interface MyInterface {
// 抽象方法(默认 public abstract)
void method1();

// 默认方法(Java 8+)
default void method2() {
System.out.println("默认方法");
}

// 静态方法(Java 8+)
static void staticMethod() {
System.out.println("静态方法");
}

// 常量(默认 public static final)
String CONSTANT = "Hello";
}

接口继承

interface Parent {
void parentMethod();
}

interface Child extends Parent {
void childMethod();
}

// 实现 Child 需要实现所有方法
class Demo implements Child {
@Override
public void parentMethod() {}

@Override
public void childMethod() {}
}

接口多继承

接口可以继承多个接口:

interface A {
void methodA();
}

interface B {
void methodB();
}

// 多继承
interface C extends A, B {
void methodC();
}

class Implementation implements C {
@Override
public void methodA() {}

@Override
public void methodB() {}

@Override
public void methodC() {}
}

默认方法

Java 8 引入了默认方法,允许在接口中提供方法实现。

为什么需要默认方法?

  1. 向后兼容:在不破坏现有实现类的情况下为接口添加新方法
  2. 提供常用功能:为所有实现类提供默认实现

基本用法

interface Drawable {
void draw();

// 默认方法
default void printInfo() {
System.out.println("这是一个可绘制的对象");
}
}

class Circle implements Drawable {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}

// 使用
Circle circle = new Circle();
circle.draw(); // 调用实现的方法
circle.printInfo(); // 调用默认方法

默认方法冲突

当一个类实现多个接口,且这些接口有相同的默认方法时,需要解决冲突:

interface A {
default void hello() {
System.out.println("Hello from A");
}
}

interface B {
default void hello() {
System.out.println("Hello from B");
}
}

// 必须重写以解决冲突
class C implements A, B {
@Override
public void hello() {
// 可以选择调用其中一个
A.super.hello();
// 或 B.super.hello();
// 或自定义实现
System.out.println("Hello from C");
}
}

默认方法的应用

interface List<E> {
void add(E e);

E get(int index);

// 默认方法:返回列表大小
default int size() {
return 0; // 默认实现
}

// 默认方法:检查是否为空
default boolean isEmpty() {
return size() == 0;
}

// 默认方法:遍历
default void forEach(Consumer<? super E> action) {
for (int i = 0; i < size(); i++) {
action.accept(get(i));
}
}
}

静态方法

Java 8 允许在接口中定义静态方法。

interface MathUtils {
static int add(int a, int b) {
return a + b;
}

static int multiply(int a, int b) {
return a * b;
}
}

// 使用
int result = MathUtils.add(3, 5); // 8

静态方法的应用

静态方法常用于提供工厂方法或工具方法:

interface Animal {
void speak();

static Animal createDog() {
return new Dog();
}

static Animal createCat() {
return new Cat();
}
}

class Dog implements Animal {
@Override
public void speak() {
System.out.println("汪汪");
}
}

class Cat implements Animal {
@Override
public void speak() {
System.out.println("喵喵");
}
}

// 使用工厂方法
Animal dog = Animal.createDog();
dog.speak();

函数式接口

只有一个抽象方法的接口称为函数式接口,可以使用 Lambda 表达式。

@FunctionalInterface 注解

@FunctionalInterface
interface MyFunction {
void doSomething(String s);

// 可以有默认方法
default void log(String msg) {
System.out.println("Log: " + msg);
}

// 可以有静态方法
static void info() {
System.out.println("这是一个函数式接口");
}
}

// 使用 Lambda 表达式
MyFunction function = s -> System.out.println("处理: " + s);
function.doSomething("Hello");

内置函数式接口

Java 8 在 java.util.function 包中提供了大量函数式接口:

import java.util.function.*;

// 无参数,有返回值
Supplier<String> supplier = () -> "Hello";

// 有参数,无返回值
Consumer<String> consumer = s -> System.out.println(s);

// 有参数,有返回值
Function<Integer, String> function = i -> "数字: " + i;

// 返回布尔值
Predicate<Integer> predicate = i -> i > 0;

// 两个参数,无返回值
BiConsumer<String, Integer> biConsumer = (s, i) -> System.out.println(s + i);

// 两个参数,有返回值
BiFunction<Integer, Integer, String> biFunction = (a, b) -> "结果: " + (a + b);

// 基本类型特化
IntPredicate intPredicate = i -> i > 0;
LongToIntFunction longToInt = l -> (int) l;

接口与抽象类

对比

特性接口抽象类
继承多实现单继承
成员变量只能是常量可以是任意类型
方法抽象方法、默认方法、静态方法抽象方法、普通方法
构造方法没有可以有
访问修饰符方法默认 public可以是 protected 等

选择

使用接口的情况:

  • 需要多继承
  • 定义行为规范,不关心状态
  • 需要为不同类提供相同功能

使用抽象类的情况:

  • 需要共享代码
  • 需要非 public 成员
  • 需要构造函数
// 接口 - 定义能力
interface Flyable {
void fly();

default void land() {
System.out.println("安全着陆");
}
}

interface Swimmable {
void swim();
}

// 抽象类 - 共享代码
abstract class Animal {
protected String name;

public Animal(String name) {
this.name = name;
}

public void eat() {
System.out.println(name + "正在吃东西");
}

public abstract void makeSound();
}

// 具体类
class Duck extends Animal implements Flyable, Swimmable {
public Duck(String name) {
super(name);
}

@Override
public void makeSound() {
System.out.println("嘎嘎");
}

@Override
public void fly() {
System.out.println(name + "正在飞");
}

@Override
public void swim() {
System.out.println(name + "正在游泳");
}
}

实际应用示例

1. 策略模式

interface PaymentStrategy {
void pay(double amount);
}

class CreditCardPayment implements PaymentStrategy {
private String cardNumber;

public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}

@Override
public void pay(double amount) {
System.out.println("使用信用卡支付:" + amount);
}
}

class PayPalPayment implements PaymentStrategy {
private String email;

public PayPalPayment(String email) {
this.email = email;
}

@Override
public void pay(double amount) {
System.out.println("使用 PayPal 支付:" + amount);
}
}

class ShoppingCart {
private PaymentStrategy paymentStrategy;

public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}

public void checkout(double amount) {
paymentStrategy.pay(amount);
}
}

// 使用
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment("1234-5678"));
cart.checkout(100.00);

2. 回调模式

interface Callback {
void onSuccess(String result);
void onError(String error);
}

class AsyncTask {
public void execute(Callback callback) {
try {
// 模拟异步操作
String result = "完成";
callback.onSuccess(result);
} catch (Exception e) {
callback.onError(e.getMessage());
}
}
}

// 使用
AsyncTask task = new AsyncTask();
task.execute(new Callback() {
@Override
public void onSuccess(String result) {
System.out.println("成功:" + result);
}

@Override
public void onError(String error) {
System.out.println("失败:" + error);
}
});

// 使用 Lambda(更简洁)
task.execute(
result -> System.out.println("成功:" + result),
error -> System.out.println("失败:" + error)
);

3. 链式构建器

interface Builder<T> {
T build();
}

class User {
private String name;
private int age;
private String email;

public static class Builder implements Builder<User> {
private String name;
private int age;
private String email;

public Builder name(String name) {
this.name = name;
return this;
}

public Builder age(int age) {
this.age = age;
return this;
}

public Builder email(String email) {
this.email = email;
return this;
}

@Override
public User build() {
User user = new User();
user.name = this.name;
user.age = this.age;
user.email = this.email;
return user;
}
}
}

// 使用
User user = new User.Builder()
.name("张三")
.age(25)
.email("[email protected]")
.build();

小结

本章我们学习了:

  1. 接口基础:定义和实现接口
  2. 接口特性:成员、继承、多继承
  3. 默认方法:解决向后兼容问题
  4. 静态方法:工具方法和工厂方法
  5. 函数式接口:与 Lambda 表达式配合使用
  6. 接口与抽象类:如何选择
  7. 实际应用:策略模式、回调模式、链式构建器

练习

  1. 定义一个 Shape 接口,包含 draw() 方法和一个默认方法
  2. 创建一个实现多个接口的类
  3. 使用函数式接口和 Lambda 表达式实现一个简单的计算器
  4. 实现策略模式的实际案例