JAVA:抽象类和接口
第一章:理解抽象的本质——为什么需要抽象类?
1.1 从具体到抽象的演进
场景:开发图形绘制系统,需要处理多种形状(圆形、矩形、三角形)
初级实现(问题:重复代码):
class Circle {void draw() { System.out.println("绘制圆形"); }double area() { return 0; } // 需要具体计算
}class Rectangle {void draw() { System.out.println("绘制矩形"); }double area() { return 0; }
}
进阶实现(引入抽象类):
abstract class Shape {// 抽象方法:无实现,强制子类完成abstract void draw();abstract double area();// 具体方法:公共逻辑void printInfo() {System.out.println("面积:" + area());}
}class Circle extends Shape {double radius;@Overridevoid draw() { System.out.println("⚪"); }@Overridedouble area() { return Math.PI * radius * radius; }
}
1.2 抽象类的核心特性
- 无法实例化:
new Shape()
会编译错误 - 可包含混合成员:抽象方法(必须实现) + 具体方法(直接继承)
- 构造方法存在:供子类初始化父类状态
abstract class Animal {String name;public Animal(String name) { this.name = name; }abstract void makeSound();
}class Dog extends Animal {public Dog(String name) { super(name); }@Overridevoid makeSound() { System.out.println(name + ":汪汪!"); }
}
1.3 抽象类的设计原则
- 模板方法模式:定义算法骨架
-
abstract class Game {// 具体方法定义流程final void play() {initialize();startPlay();endPlay();}abstract void initialize();abstract void startPlay();abstract void endPlay(); }class Chess extends Game {void initialize() { System.out.println("摆棋盘"); }void startPlay() { System.out.println("开始对弈"); }void endPlay() { System.out.println("收拾棋子"); } }
第二章:接口——行为的契约
2.1 接口的诞生背景
需求:实现会飞的鸟和会飞的飞机,但飞行方式不同
传统继承的局限:
-
// 错误的多重继承尝试 class Bird extends Animal, Flyable { ... } // Java不支持
接口解决方案:
-
interface Flyable {void fly(); // 默认public abstract }class Bird extends Animal implements Flyable {public void fly() { System.out.println("振翅高飞"); } }class Airplane implements Flyable {public void fly() { System.out.println("引擎推进"); } }
2.2 接口的现代进化(Java 8+)
默认方法:解决接口升级问题
-
interface USB {default void connect() {System.out.println("USB设备已连接");}void transferData(); }class FlashDrive implements USB {public void transferData() {System.out.println("传输文件...");}// 自动继承connect() }
静态方法:工具方法聚合
interface MathUtils {static int max(int a, int b) {return a > b ? a : b;} }// 使用:MathUtils.max(5,3)
2.3 接口的多继承威力
interface Swimmable {void swim();
}interface Diving extends Swimmable {void deepDive();
}class Penguin extends Bird implements Diving {public void swim() { System.out.println("企鹅划水"); }public void deepDive() { System.out.println("潜入深海"); }
}
第三章:抽象类 vs 接口——如何正确选择?
3.1 概念对比表
特性 | 抽象类 | 接口 |
---|---|---|
实例化 | 不能 | 不能 |
方法实现 | 可包含具体方法 | Java 8+支持默认方法 |
变量 | 任意类型 | 默认public static final |
构造方法 | 有 | 无 |
继承方式 | 单继承 | 多实现 |
设计目的 | 代码复用(IS-A关系) | 定义行为(CAN-DO关系) |
3.2 典型应用场景
抽象类适用场景:
- 多个相关类共享代码
- 需要定义非public成员
- 需要定义子类的公共状态
接口适用场景:
- 定义跨继承树的行为
- 需要多重继承
- 定义API契约
3.3 混合使用案例
abstract class Animal {String name;public Animal(String name) { this.name = name; }abstract void eat();
}interface Swimmable {void swim();
}class Dolphin extends Animal implements Swimmable {public Dolphin() { super("海豚"); }@Overridevoid eat() { System.out.println("吃鱼"); }@Overridepublic void swim() { System.out.println("优雅游动"); }
}
第四章:深入接口内部——从字节码看本质
4.1 接口的编译产物
源代码:
interface Logger {void log(String message);default void debug(String msg) {System.out.println("[DEBUG] " + msg);}
}
反编译结果:
public interface Logger {public abstract void log(String message);public void debug(String msg) { /* 默认实现 */ }
}
4.2 默认方法的冲突解决
规则:
- 类中的方法优先级最高
- 子接口覆盖父接口
- 必须显式解决冲突
示例:
interface A {default void show() { System.out.println("A"); }
}interface B {default void show() { System.out.println("B"); }
}class C implements A, B {// 必须重写@Overridepublic void show() {A.super.show(); // 明确调用A的实现}
}
第五章:实战演练——电商系统设计
5.1 需求分析
- 商品分类:电子产品(保修期)、服饰(尺寸)
- 支付方式:信用卡、支付宝
- 物流服务:标准、加急
5.2 类图设计
<<abstract>>
Product
+ name: String
+ price: double
+ description(): void▲|
+------+-------+
| |
Electronics Clothing▲ ▲| |
+------+------+ +---+---+
| | | |
Laptop Phone TShirt Dress<<interface>>
Payable
+ pay(): boolean<<interface>>
Shippable
+ ship(): void
5.3 完整代码实现
// 抽象商品类
abstract class Product {String name;double price;public Product(String name, double price) {this.name = name;this.price = price;}abstract void description();
}// 电子产品子类
class Electronics extends Product {int warrantyMonths;public Electronics(String name, double price, int warranty) {super(name, price);this.warrantyMonths = warranty;}@Overridevoid description() {System.out.printf("%s 保修期:%d个月\n", name, warrantyMonths);}
}// 支付接口
interface Payable {boolean pay(double amount);
}// 物流接口
interface Shippable {void ship(String address);
}// 具体商品实现
class Laptop extends Electronics implements Shippable {public Laptop() {super("高端笔记本", 9999.99, 24);}public boolean pay(double amount) {System.out.println("信用卡支付:" + amount);return true;}public void ship(String address) {System.out.println("快递发货至:" + address);}
}
第六章:常见陷阱与最佳实践
6.1 易犯错误
-
滥用继承:将"has-a"关系设计成继承
// 错误:汽车不是引擎的一种
class Car extends Engine { ... }// 正确:使用组合
class Car {Engine engine;
}
2.过度抽象:过早创建不必要的抽象
// 不需要抽象的情况
abstract class StringUtils { // 应改为final类+私有构造static String reverse(String s) { ... }
}
6.2 设计原则
-
面向接口编程:声明变量时优先使用接口类型
-
List<String> list = new ArrayList<>(); // 正确 ArrayList<String> list = new ArrayList<>(); // 不够灵活
-
接口隔离原则:避免臃肿接口
-
// 错误:多功能混合接口 interface AnimalActions {void eat();void fly();void swim(); }// 正确:拆分接口 interface Flyable { void fly(); } interface Swimmable { void swim(); }
第七章:Java 17新特性——密封类与接口
7.1 密封类(Sealed Classes)
-
作用:限制类的继承
-
public abstract sealed class Shape permits Circle, Rectangle, Triangle {// 仅允许指定子类 }final class Circle extends Shape { ... }
7.2 密封接口
sealed interface FileFormat permits JSON, XML, CSV { ... }
第八章:综合练习与答案
8.1 练习题
-
设计
Logger
抽象类,包含:- 抽象方法
log(String message)
- 具体方法
getTimestamp()
- 子类
FileLogger
和ConsoleLogger
- 抽象方法
-
创建
Authenticator
接口,包含:- 默认方法
encrypt(String password)
- 抽象方法
login(String user, String pass)
- 实现类
DatabaseAuthenticator
- 默认方法
8.2 参考答案
// 抽象Logger
abstract class Logger {String getTimestamp() {return Instant.now().toString();}abstract void log(String message);
}class FileLogger extends Logger {@Overridevoid log(String message) {String entry = getTimestamp() + " - " + message;// 写入文件...}
}// 认证接口
interface Authenticator {default String encrypt(String password) {return Base64.getEncoder().encodeToString(password.getBytes());}boolean login(String user, String password);
}class DatabaseAuthenticator implements Authenticator {@Overridepublic boolean login(String user, String pass) {String encrypted = encrypt(pass);// 数据库验证...return true;}
}
总结:
- 抽象类的定义与使用场景
- 接口的演进与现代特性
- 抽象类与接口的对比选择
- 面向接口编程的最佳实践
- 复杂系统的分层设计技巧