1. 引言

面向对象编程(OOP)是Java语言的基石,理解其核心概念对于编写高质量、可维护的代码至关重要。本文将深入探讨Java面向对象编程中的四个关键概念:多态抽象类内部类接口,并结合五大设计原则(SOLID原则)展示如何在实际开发中应用这些概念。

2. 多态(Polymorphism)

多态是面向对象编程的三大特性之一(封装、继承、多态),它允许不同类的对象对同一消息做出不同的响应。

2.1 多态的类型

Java中的多态主要分为两种:

  1. 编译时多态(静态多态):通过方法重载实现
  2. 运行时多态(动态多态):通过方法重写和继承实现

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 内部类的类型

  1. 成员内部类(Member Inner Class)
  2. 静态内部类(Static Nested Class)
  3. 局部内部类(Local Inner Class)
  4. 匿名内部类(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);
        // 订单处理逻

更多推荐