Java接口详解:定义、实现与默认方法
Java接口详解:定义、实现与默认方法
概述
接口(Interface)是Java中定义抽象行为的机制。接口定义了一组方法规范,类可以实现接口来提供具体实现。接口支持多继承,一个类可以实现多个接口。
1. 接口的定义
基本接口
// 定义接口
public interface Drawable {
// 抽象方法(默认public abstract)
void draw();
// 常量(默认public static final)
int MAX_WIDTH = 100;
int MAX_HEIGHT = 100;
// 默认方法(Java 8+)
default void fill() {
System.out.println("填充默认颜色");
}
// 静态方法(Java 8+)
static void printInfo() {
System.out.println("这是一个可绘制的接口");
}
// 私有方法(Java 9+)
private void validate() {
System.out.println("验证绘图参数");
}
}
// 实现接口
public class Circle implements Drawable {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("绘制圆形,半径: " + radius);
}
}
// 测试
public class InterfaceTest {
public static void main(String[] args) {
Circle circle = new Circle(5);
circle.draw(); // 调用实现的方法
circle.fill(); // 调用默认方法
Drawable.printInfo(); // 调用静态方法
System.out.println("最大宽度: " + Drawable.MAX_WIDTH); // 访问常量
}
}
2. 多接口实现
一个类实现多个接口
public interface Swimmable {
void swim();
default void floatOnWater() {
System.out.println("漂浮在水面上");
}
}
public interface Flyable {
void fly();
default void glide() {
System.out.println("滑翔飞行");
}
}
public interface Walkable {
void walk();
}
// 实现多个接口
public class Duck implements Swimmable, Flyable, Walkable {
@Override
public void swim() {
System.out.println("鸭子游泳");
}
@Override
public void fly() {
System.out.println("鸭子飞行");
}
@Override
public void walk() {
System.out.println("鸭子走路");
}
}
// 测试
public class MultiInterfaceTest {
public static void main(String[] args) {
Duck duck = new Duck();
duck.swim();
duck.fly();
duck.walk();
duck.floatOnWater();
duck.glide();
// 接口类型引用
Swimmable swimmable = duck;
swimmable.swim();
Flyable flyable = duck;
flyable.fly();
}
}
3. 接口继承
// 父接口
public interface Shape {
double area();
double perimeter();
default void display() {
System.out.println("面积: " + area());
System.out.println("周长: " + perimeter());
}
}
// 子接口继承父接口
public interface Resizable extends Shape {
void resize(double factor);
@Override
default void display() {
Shape.super.display(); // 调用父接口的默认方法
System.out.println("调整大小");
}
}
// 实现子接口
public class Circle implements Resizable {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
@Override
public void resize(double factor) {
this.radius *= factor;
System.out.println("调整后半径: " + radius);
}
}
// 测试
public class InterfaceInheritanceTest {
public static void main(String[] args) {
Circle circle = new Circle(5);
circle.display();
circle.resize(2);
circle.display();
}
}
4. 函数式接口
单抽象方法接口
@FunctionalInterface // 注解表示函数式接口
public interface Calculator {
int calculate(int a, int b);
// 可以有默认方法
default int add(int a, int b) {
return a + b;
}
// 可以有静态方法
static int multiply(int a, int b) {
return a * b;
}
}
// 使用Lambda表达式实现函数式接口
public class FunctionalInterfaceTest {
public static void main(String[] args) {
// 使用Lambda表达式
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
Calculator multiply = (a, b) -> a * b;
System.out.println("加法: " + add.calculate(10, 5));
System.out.println("减法: " + subtract.calculate(10, 5));
System.out.println("乘法: " + multiply.calculate(10, 5));
// 使用方法引用
Calculator add2 = Integer::sum;
System.out.println("加法2: " + add2.calculate(10, 5));
}
}
5. 接口与抽象类的区别
// 抽象类
public abstract class AbstractAnimal {
protected String name;
public AbstractAnimal(String name) {
this.name = name;
}
public abstract void sound();
public void eat() {
System.out.println(name + "吃东西");
}
}
// 接口
public interface AnimalInterface {
void sound();
default void eat() {
System.out.println("吃东西");
}
}
// 类可以继承一个抽象类,但可以实现多个接口
public class Dog extends AbstractAnimal implements AnimalInterface {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
System.out.println("汪汪汪");
}
@Override
public void eat() {
System.out.println(name + "吃骨头");
}
}
6. 实际应用示例
插件系统
public interface Plugin {
String getName();
String getVersion();
void execute();
default void log(String message) {
System.out.println("[" + getName() + "] " + message);
}
}
public class LoggerPlugin implements Plugin {
@Override
public String getName() {
return "Logger";
}
@Override
public String getVersion() {
return "1.0.0";
}
@Override
public void execute() {
log("执行日志记录");
}
}
public class DatabasePlugin implements Plugin {
@Override
public String getName() {
return "Database";
}
@Override
public String getVersion() {
return "2.0.0";
}
@Override
public void execute() {
log("执行数据库操作");
}
}
public class PluginManager {
private List<Plugin> plugins = new ArrayList<>();
public void registerPlugin(Plugin plugin) {
plugins.add(plugin);
plugin.log("插件已注册");
}
public void executeAllPlugins() {
for (Plugin plugin : plugins) {
plugin.execute();
}
}
}
public class PluginTest {
public static void main(String[] args) {
PluginManager manager = new PluginManager();
manager.registerPlugin(new LoggerPlugin());
manager.registerPlugin(new DatabasePlugin());
System.out.println("---");
manager.executeAllPlugins();
}
}
7. 最佳实践
- 使用接口定义行为:接口用于定义类应该具有的行为
- 使用抽象类共享代码:当多个类有共同代码时,使用抽象类
- 优先使用接口:需要多继承时使用接口
- 保持接口小而专注:每个接口应该只定义一组相关的功能
- 使用@FunctionalInterface:单抽象方法接口使用此注解
总结
接口是Java中定义抽象行为的重要机制。通过接口,可以实现多继承、定义契约、支持Lambda表达式等。理解接口的使用规则和最佳实践,对于设计灵活、可扩展的Java程序至关重要。