深入理解Java面向对象:多态、抽象类、内部类、接口与五大设计原则
·
1. 引言
面向对象编程(OOP)是Java语言的基石,理解其核心概念对于编写高质量、可维护的代码至关重要。本文将深入探讨Java面向对象编程中的四个关键概念:多态、抽象类、内部类、接口,并结合五大设计原则(SOLID原则)展示如何在实际开发中应用这些概念。
2. 多态(Polymorphism)
多态是面向对象编程的三大特性之一(封装、继承、多态),它允许不同类的对象对同一消息做出不同的响应。
2.1 多态的类型
Java中的多态主要分为两种:
- 编译时多态(静态多态):通过方法重载实现
- 运行时多态(动态多态):通过方法重写和继承实现
2.2 代码示例
// 父类
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
// 方法重载 - 编译时多态
public void makeSound(String type) {
System.out.println(type + "动物发出声音");
}
}
// 子类1
class Dog extends Animal {
// 方法重写 - 运行时多态
@Override
public void makeSound() {
System.out.println("汪汪汪");
}
}
// 子类2
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵喵");
}
}
public class PolymorphismDemo {
public static void main(String[] args) {
// 运行时多态示例
Animal animal1 = new Dog(); // 向上转型
Animal animal2 = new Cat();
animal1.makeSound(); // 输出:汪汪汪
animal2.makeSound(); // 输出:喵喵喵
// 编译时多态示例
Animal animal3 = new Animal();
animal3.makeSound(); // 输出:动物发出声音
animal3.makeSound("大型"); // 输出:大型动物发出声音
}
}
2.3 多态的优势
- 提高代码扩展性:新增子类无需修改现有代码
- 增强代码可维护性:统一的接口处理不同类型的对象
- 实现松耦合:减少类之间的依赖关系
3. 抽象类(Abstract Class)
抽象类是不能被实例化的类,用于定义子类必须实现的抽象方法。
3.1 抽象类的特点
- 使用
abstract关键字声明 - 可以包含抽象方法和具体方法
- 可以有构造方法,但不能直接实例化
- 子类必须实现所有抽象方法(除非子类也是抽象类)
3.2 代码示例
// 抽象类
abstract class Shape {
protected String color;
// 构造方法
public Shape(String color) {
this.color = color;
}
// 抽象方法 - 子类必须实现
public abstract double calculateArea();
// 具体方法 - 子类可以继承使用
public void displayColor() {
System.out.println("形状颜色:" + color);
}
}
// 具体子类1
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
// 具体子类2
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class AbstractClassDemo {
public static void main(String[] args) {
Shape circle = new Circle("红色", 5.0);
Shape rectangle = new Rectangle("蓝色", 4.0, 6.0);
circle.displayColor();
System.out.println("圆形面积:" + circle.calculateArea());
rectangle.displayColor();
System.out.println("矩形面积:" + rectangle.calculateArea());
}
}
4. 接口(Interface)
接口是Java中实现多继承的方式,定义了一组方法的规范。
4.1 接口的特点(Java 8+)
- 使用
interface关键字声明 - 所有方法默认是
public abstract(Java 8之前) - 可以包含默认方法(default methods)
- 可以包含静态方法
- 可以包含常量(默认
public static final) - 支持多重继承(一个类可以实现多个接口)
4.2 代码示例
// 接口1:可飞行的
interface Flyable {
// 抽象方法
void fly();
// 默认方法(Java 8+)
default void takeOff() {
System.out.println("准备起飞...");
}
// 静态方法(Java 8+)
static int getMaxAltitude() {
return 10000;
}
}
// 接口2:可鸣叫的
interface Honkable {
void honk();
}
// 接口继承
interface AdvancedFlyable extends Flyable {
void performStunt();
}
// 类实现多个接口
class Airplane implements Flyable, Honkable {
private String model;
public Airplane(String model) {
this.model = model;
}
@Override
public void fly() {
System.out.println(model + "飞机正在飞行");
}
@Override
public void honk() {
System.out.println("飞机鸣笛:嘟嘟嘟");
}
}
// 实现继承的接口
class FighterJet implements AdvancedFlyable {
@Override
public void fly() {
System.out.println("战斗机高速飞行");
}
@Override
public void performStunt() {
System.out.println("战斗机表演特技:翻滚");
}
}
public class InterfaceDemo {
public static void main(String[] args) {
// 使用接口类型引用
Flyable airplane = new Airplane("波音747");
airplane.takeOff();
airplane.fly();
// 调用接口静态方法
System.out.println("最大飞行高度:" + Flyable.getMaxAltitude() + "米");
// 多重接口
Honkable honkable = (Honkable) airplane;
honkable.honk();
// 接口继承
AdvancedFlyable jet = new FighterJet();
jet.fly();
jet.performStunt();
}
}
5. 内部类(Inner Class)
内部类是定义在另一个类内部的类,可以访问外部类的私有成员。
5.1 内部类的类型
- 成员内部类(Member Inner Class)
- 静态内部类(Static Nested Class)
- 局部内部类(Local Inner Class)
- 匿名内部类(Anonymous Inner Class)
5.2 代码示例
// 外部类
class OuterClass {
private String outerField = "外部类字段";
private static String staticOuterField = "静态外部类字段";
// 成员内部类
class MemberInnerClass {
private String innerField = "成员内部类字段";
public void display() {
// 可以访问外部类的私有成员
System.out.println("访问外部类字段:" + outerField);
System.out.println("内部类字段:" + innerField);
}
}
// 静态内部类
static class StaticNestedClass {
public void display() {
// 只能访问外部类的静态成员
System.out.println("访问静态外部类字段:" + staticOuterField);
// System.out.println(outerField); // 错误:不能访问非静态成员
}
}
// 方法中的局部内部类
public void methodWithLocalClass() {
final String localVar = "局部变量";
class LocalInnerClass {
public void display() {
System.out.println("局部内部类访问:" + localVar);
System.out.println("访问外部类字段:" + outerField);
}
}
LocalInnerClass local = new LocalInnerClass();
local.display();
}
// 使用匿名内部类
public void useAnonymousClass() {
// 实现Runnable接口的匿名内部类
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类执行,访问外部字段:" + outerField);
}
};
new Thread(runnable).start();
}
}
public class InnerClassDemo {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
// 创建成员内部类实例
OuterClass.MemberInnerClass memberInner = outer.new MemberInnerClass();
memberInner.display();
// 创建静态内部类实例
OuterClass.StaticNestedClass staticInner = new OuterClass.StaticNestedClass();
staticInner.display();
// 调用包含局部内部类的方法
outer.methodWithLocalClass();
// 调用使用匿名内部类的方法
outer.useAnonymousClass();
}
}
6. 五大设计原则(SOLID)
SOLID原则是面向对象设计的五个基本原则,由Robert C. Martin提出。
6.1 单一职责原则(SRP)
一个类应该只有一个引起变化的原因。
// 违反SRP的示例
class UserService {
public void addUser(User user) {
// 业务逻辑
}
public void sendEmail(User user, String message) {
// 发送邮件逻辑
}
public void logActivity(User user, String activity) {
// 日志记录逻辑
}
}
// 遵循SRP的示例
class UserService {
private EmailService emailService;
private Logger logger;
public void addUser(User user) {
// 业务逻辑
emailService.sendWelcomeEmail(user);
logger.log("用户添加:" + user.getName());
}
}
class EmailService {
public void sendWelcomeEmail(User user) {
// 发送欢迎邮件
}
}
class Logger {
public void log(String message) {
// 记录日志
}
}
6.2 开闭原则(OCP)
软件实体应该对扩展开放,对修改关闭。
// 违反OCP的示例
class DiscountCalculator {
public double calculateDiscount(String customerType, double amount) {
if ("REGULAR".equals(customerType)) {
return amount * 0.1;
} else if ("VIP".equals(customerType)) {
return amount * 0.2;
}
return 0;
}
}
// 遵循OCP的示例
interface DiscountStrategy {
double calculateDiscount(double amount);
}
class RegularCustomerDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double amount) {
return amount * 0.1;
}
}
class VIPCustomerDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double amount) {
return amount * 0.2;
}
}
class DiscountCalculator {
private DiscountStrategy strategy;
public DiscountCalculator(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calculate(double amount) {
return strategy.calculateDiscount(amount);
}
}
6.3 里氏替换原则(LSP)
子类必须能够替换它们的父类而不影响程序的正确性。
// 违反LSP的示例
class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
class Square extends Rectangle {
@Override
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width); // 违反LSP:改变了父类的行为
}
@Override
public void setHeight(int height) {
super.setHeight(height);
super.setWidth(height); // 违反LSP:改变了父类的行为
}
}
// 遵循LSP的示例
interface Shape {
int getArea();
}
class Rectangle implements Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public int getArea() {
return width * height;
}
}
class Square implements Shape {
private int side;
public Square(int side) {
this.side = side;
}
@Override
public int getArea() {
return side * side;
}
}
6.4 接口隔离原则(ISP)
客户端不应该依赖它不需要的接口。
// 违反ISP的示例
interface Worker {
void work();
void eat();
void sleep();
}
class Robot implements Worker {
@Override
public void work() {
System.out.println("机器人工作");
}
@Override
public void eat() {
// 机器人不需要吃饭,但必须实现
throw new UnsupportedOperationException();
}
@Override
public void sleep() {
// 机器人不需要睡觉,但必须实现
throw new UnsupportedOperationException();
}
}
// 遵循ISP的示例
interface Workable {
void work();
}
interface Eatable {
void eat();
}
interface Sleepable {
void sleep();
}
class HumanWorker implements Workable, Eatable, Sleepable {
@Override
public void work() {
System.out.println("人类工作");
}
@Override
public void eat() {
System.out.println("人类吃饭");
}
@Override
public void sleep() {
System.out.println("人类睡觉");
}
}
class RobotWorker implements Workable {
@Override
public void work() {
System.out.println("机器人工作");
}
}
6.5 依赖倒置原则(DIP)
高层模块不应该依赖低层模块,两者都应该依赖抽象。
// 违反DIP的示例
class EmailService {
public void sendEmail(String message) {
System.out.println("发送邮件:" + message);
}
}
class Notification {
private EmailService emailService;
public Notification() {
this.emailService = new EmailService(); // 直接依赖具体类
}
public void sendNotification(String message) {
emailService.sendEmail(message);
}
}
// 遵循DIP的示例
interface MessageService {
void sendMessage(String message);
}
class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("发送邮件:" + message);
}
}
class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("发送短信:" + message);
}
}
class Notification {
private MessageService messageService;
// 依赖注入
public Notification(MessageService messageService) {
this.messageService = messageService;
}
public void sendNotification(String message) {
messageService.sendMessage(message);
}
}
7. 综合应用示例
下面是一个综合应用所有概念的完整示例:
// 接口定义
interface PaymentStrategy {
void pay(double amount);
String getPaymentMethod();
}
// 具体支付策略
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public void pay(double amount) {
System.out.println("使用信用卡支付:" + amount + "元");
System.out.println("卡号:" + maskCardNumber(cardNumber));
}
@Override
public String getPaymentMethod() {
return "信用卡";
}
private String maskCardNumber(String cardNumber) {
return "****-****-****-" + cardNumber.substring(cardNumber.length() - 4);
}
}
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 + "元");
System.out.println("邮箱:" + email);
}
@Override
public String getPaymentMethod() {
return "PayPal";
}
}
// 抽象订单类
abstract class Order {
protected String orderId;
protected double amount;
protected PaymentStrategy paymentStrategy;
public Order(String orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
}
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
// 抽象方法
public abstract void processOrder();
// 具体方法
public void makePayment() {
if (paymentStrategy == null) {
throw new IllegalStateException("未设置支付方式");
}
System.out.println("订单ID:" + orderId);
System.out.println("支付方式:" + paymentStrategy.getPaymentMethod());
paymentStrategy.pay(amount);
}
// 内部类:订单详情
public class OrderDetails {
public void display() {
System.out.println("订单详情:");
System.out.println("订单ID:" + orderId);
System.out.println("金额:" + amount);
System.out.println("支付方式:" +
(paymentStrategy != null ? paymentStrategy.getPaymentMethod() : "未设置"));
}
}
}
// 具体订单类
class OnlineOrder extends Order {
private String shippingAddress;
public OnlineOrder(String orderId, double amount, String shippingAddress) {
super(orderId, amount);
this.shippingAddress = shippingAddress;
}
@Override
public void processOrder() {
System.out.println("处理在线订单,配送地址:" + shippingAddress);
// 订单处理逻
更多推荐


所有评论(0)