Skip to content

面向对象进阶

本章将深入讲解 Java 面向对象的高级特性,包括继承、多态、抽象类和接口。

继承

继承是面向对象的核心特性之一,允许子类继承父类的属性和方法。

继承的基本概念

text
┌─────────────────────────────────────────────────────────────────┐
│                        继承关系                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│                      Animal(父类)                              │
│                     /          \                                │
│                 Dog(子类)    Cat(子类)                       │
│                                                                 │
│  子类继承父类的:                                                 │
│  - public 和 protected 成员                                     │
│  - 默认访问权限的成员(同一包中)                                  │
│                                                                 │
│  子类不继承:                                                     │
│  - private 成员                                                 │
│  - 构造方法                                                      │
└─────────────────────────────────────────────────────────────────┘

继承的实现

java
// 父类:动物类
class Animal {
    String name;
    int age;
    
    public Animal() {
        System.out.println("Animal 无参构造");
    }
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal 有参构造");
    }
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

// 子类:狗类
class Dog extends Animal {
    String breed;  // 品种
    
    public Dog() {
        super();  // 调用父类无参构造(默认)
        System.out.println("Dog 无参构造");
    }
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类有参构造
        this.breed = breed;
        System.out.println("Dog 有参构造");
    }
    
    // 子类特有方法
    public void bark() {
        System.out.println(name + "正在汪汪叫");
    }
    
    // 重写父类方法
    @Override
    public void eat() {
        System.out.println(name + "正在吃狗粮");
    }
}

public class InheritanceDemo {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财", 3, "金毛");
        
        // 调用继承的方法
        dog.sleep();
        
        // 调用重写的方法
        dog.eat();
        
        // 调用子类特有方法
        dog.bark();
        
        System.out.println("\n狗的信息:");
        System.out.println("名字:" + dog.name);
        System.out.println("年龄:" + dog.age);
        System.out.println("品种:" + dog.breed);
    }
}

方法重写

java
class Shape {
    public void draw() {
        System.out.println("绘制图形");
    }
    
    public double getArea() {
        return 0;
    }
}

class Circle extends Shape {
    double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    // 重写父类方法
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    double width;
    double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
    
    @Override
    public double getArea() {
        return width * height;
    }
}

public class OverrideDemo {
    public static void main(String[] args) {
        Shape shape1 = new Circle(5);
        Shape shape2 = new Rectangle(4, 6);
        
        shape1.draw();  // 绘制圆形
        shape2.draw();  // 绘制矩形
        
        System.out.println("圆面积:" + shape1.getArea());
        System.out.println("矩形面积:" + shape2.getArea());
    }
}

super 关键字

java
class Parent {
    String name = "父类";
    
    public Parent() {
        System.out.println("父类构造方法");
    }
    
    public void method() {
        System.out.println("父类方法");
    }
}

class Child extends Parent {
    String name = "子类";
    
    public Child() {
        super();  // 调用父类构造方法(必须放在第一行)
        System.out.println("子类构造方法");
    }
    
    public void show() {
        System.out.println(name);        // 子类的 name
        System.out.println(super.name);  // 父类的 name
    }
    
    @Override
    public void method() {
        super.method();  // 调用父类方法
        System.out.println("子类方法");
    }
}

public class SuperDemo {
    public static void main(String[] args) {
        Child child = new Child();
        child.show();
        child.method();
    }
}

多态

多态是指同一行为具有不同表现形式的能力。

多态的实现

java
// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

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

class Cow 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();
        Animal animal3 = new Cow();
        
        // 同一方法调用,不同表现
        animal1.makeSound();  // 汪汪汪
        animal2.makeSound();  // 喵喵喵
        animal3.makeSound();  // 哞哞哞
        
        // 多态数组
        Animal[] animals = {new Dog(), new Cat(), new Cow()};
        for (Animal animal : animals) {
            animal.makeSound();
        }
        
        // 多态作为方法参数
        System.out.println("\n方法参数多态:");
        animalSound(new Dog());
        animalSound(new Cat());
    }
    
    // 多态作为方法参数
    public static void animalSound(Animal animal) {
        animal.makeSound();
    }
}

类型转换

java
class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("狗吃骨头");
    }
    
    public void bark() {
        System.out.println("汪汪叫");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void meow() {
        System.out.println("喵喵叫");
    }
}

public class TypeConversion {
    public static void main(String[] args) {
        // 向上转型(自动):子类 → 父类
        Animal animal = new Dog();  // 向上转型
        animal.eat();  // 调用 Dog 的 eat
        
        // animal.bark();  // 编译错误:父类引用不能调用子类特有方法
        
        // 向下转型(强制):父类 → 子类
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;  // 向下转型
            dog.bark();  // 现在可以调用子类特有方法
        }
        
        // instanceof 判断对象类型
        Animal animal2 = new Cat();
        System.out.println("animal2 是 Dog 吗?" + (animal2 instanceof Dog));    // false
        System.out.println("animal2 是 Cat 吗?" + (animal2 instanceof Cat));    // true
        System.out.println("animal2 是 Animal 吗?" + (animal2 instanceof Animal));  // true
        
        // 类型转换异常
        if (animal2 instanceof Dog) {
            Dog dog = (Dog) animal2;  // 不会执行
        } else {
            System.out.println("animal2 不是 Dog 类型");
        }
        
        // ClassCastException 示例
        try {
            Dog dog = (Dog) animal2;  // ClassCastException
        } catch (ClassCastException e) {
            System.out.println("类型转换异常:" + e.getMessage());
        }
    }
}

多态应用示例

java
// 抽象的支付方式
abstract class Payment {
    protected double amount;
    
    public Payment(double amount) {
        this.amount = amount;
    }
    
    public abstract void pay();
}

// 支付宝支付
class Alipay extends Payment {
    public Alipay(double amount) {
        super(amount);
    }
    
    @Override
    public void pay() {
        System.out.println("使用支付宝支付:" + amount + "元");
    }
}

// 微信支付
class WeChatPay extends Payment {
    public WeChatPay(double amount) {
        super(amount);
    }
    
    @Override
    public void pay() {
        System.out.println("使用微信支付:" + amount + "元");
    }
}

// 银行卡支付
class BankCardPay extends Payment {
    private String cardNumber;
    
    public BankCardPay(double amount, String cardNumber) {
        super(amount);
        this.cardNumber = cardNumber;
    }
    
    @Override
    public void pay() {
        System.out.println("使用银行卡(" + cardNumber + ")支付:" + amount + "元");
    }
}

public class PaymentDemo {
    public static void main(String[] args) {
        // 多态数组
        Payment[] payments = {
            new Alipay(100.0),
            new WeChatPay(200.0),
            new BankCardPay(300.0, "6222****1234")
        };
        
        // 统一处理支付
        for (Payment payment : payments) {
            payment.pay();
        }
    }
}

抽象类

抽象类是不能被实例化的类,用于定义子类的通用模板。

抽象类定义

java
// 抽象类:图形
abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // 抽象方法:没有方法体,子类必须实现
    public abstract double getArea();
    public abstract double getPerimeter();
    
    // 具体方法:子类可以直接继承
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    // 显示信息
    public void showInfo() {
        System.out.println("颜色:" + color);
        System.out.println("面积:" + getArea());
        System.out.println("周长:" + getPerimeter());
    }
}

// 具体子类:圆形
class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

// 具体子类:矩形
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 getArea() {
        return width * height;
    }
    
    @Override
    public double getPerimeter() {
        return 2 * (width + height);
    }
}

public class AbstractDemo {
    public static void main(String[] args) {
        // Shape shape = new Shape("红色");  // 编译错误:抽象类不能实例化
        
        Shape circle = new Circle("红色", 5);
        Shape rectangle = new Rectangle("蓝色", 4, 6);
        
        circle.showInfo();
        System.out.println();
        rectangle.showInfo();
    }
}

抽象类特点

text
┌─────────────────────────────────────────────────────────────────┐
│                      抽象类特点                                  │
├─────────────────────────────────────────────────────────────────┤
│  1. 使用 abstract 关键字修饰                                     │
│  2. 不能被实例化                                                 │
│  3. 可以有抽象方法(没有方法体)                                  │
│  4. 可以有具体方法、构造方法、成员变量                            │
│  5. 子类必须实现所有抽象方法,否则也是抽象类                       │
│  6. 可以有 main 方法                                             │
└─────────────────────────────────────────────────────────────────┘

接口

接口是一种完全抽象的类型,定义了一组方法的规范。

接口定义

java
// 接口:飞行能力
interface Flyable {
    // 常量:默认 public static final
    int MAX_HEIGHT = 10000;
    
    // 抽象方法:默认 public abstract
    void fly();
    
    // 默认方法(Java 8+):可以有方法体
    default void showMaxHeight() {
        System.out.println("最大飞行高度:" + MAX_HEIGHT);
    }
    
    // 静态方法(Java 8+)
    static void checkWeather() {
        System.out.println("检查天气状况");
    }
}

// 接口:游泳能力
interface Swimmable {
    void swim();
}

// 实现类:鸭子(可以飞也可以游泳)
class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("鸭子在低空飞行");
    }
    
    @Override
    public void swim() {
        System.out.println("鸭子在水里游泳");
    }
}

// 实现类:飞机(只能飞)
class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机在万米高空飞行");
    }
}

public class InterfaceDemo {
    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.fly();
        duck.swim();
        duck.showMaxHeight();  // 调用默认方法
        
        Flyable.checkWeather();  // 调用静态方法
        
        System.out.println("最大高度:" + Flyable.MAX_HEIGHT);  // 访问常量
        
        // 多态
        Flyable flyable1 = new Duck();
        Flyable flyable2 = new Airplane();
        
        flyable1.fly();
        flyable2.fly();
    }
}

接口继承

java
// 基础接口
interface A {
    void methodA();
}

interface B {
    void methodB();
}

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

// 实现类
class ImplC implements C {
    @Override
    public void methodA() {
        System.out.println("实现 methodA");
    }
    
    @Override
    public void methodB() {
        System.out.println("实现 methodB");
    }
    
    @Override
    public void methodC() {
        System.out.println("实现 methodC");
    }
}

public class InterfaceInheritance {
    public static void main(String[] args) {
        C impl = new ImplC();
        impl.methodA();
        impl.methodB();
        impl.methodC();
    }
}

接口与抽象类对比

text
┌─────────────────────────────────────────────────────────────────┐
│                   接口 vs 抽象类                                 │
├─────────────────────────────────────────────────────────────────┤
│        特性         │      接口        │     抽象类             │
├─────────────────────────────────────────────────────────────────┤
│  实例化             │       不能       │       不能             │
│  构造方法           │       没有       │       可以有           │
│  成员变量           │    只能是常量    │     可以有变量         │
│  抽象方法           │       可以       │       可以             │
│  具体方法           │   默认方法(Java8)│       可以             │
│  多继承             │       支持       │      不支持            │
│  设计理念           │      "能做什么"  │     "是什么"           │
└─────────────────────────────────────────────────────────────────┘

final 关键字

final 关键字表示"最终的",不可改变的。

java
// final 类:不能被继承
final class FinalClass {
    // final 变量:只能赋值一次(常量)
    final int MAX_VALUE = 100;
    
    // final 方法:不能被重写
    public final void finalMethod() {
        System.out.println("final 方法不能被重写");
    }
    
    // final 参数:方法内不能修改
    public void method(final int param) {
        // param = 10;  // 编译错误
        System.out.println(param);
    }
}

// class SubClass extends FinalClass { }  // 编译错误:不能继承 final 类

public class FinalDemo {
    public static void main(String[] args) {
        FinalClass fc = new FinalClass();
        
        // fc.MAX_VALUE = 200;  // 编译错误:不能修改 final 变量
        
        // final 引用变量:引用不能变,但对象内容可以变
        final int[] arr = {1, 2, 3};
        arr[0] = 100;  // 可以修改数组元素
        // arr = new int[5];  // 编译错误:不能改变引用
    }
}

内部类

内部类是定义在另一个类内部的类。

成员内部类

java
class Outer {
    private String outerField = "外部类字段";
    private static String outerStaticField = "外部类静态字段";
    
    // 成员内部类
    class Inner {
        private String innerField = "内部类字段";
        
        public void show() {
            System.out.println("访问外部类字段:" + outerField);
            System.out.println("访问内部类字段:" + innerField);
        }
    }
    
    public void createInner() {
        Inner inner = new Inner();
        inner.show();
    }
}

public class InnerClassDemo {
    public static void main(String[] args) {
        // 创建成员内部类对象
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.show();
    }
}

静态内部类

java
class Outer {
    private static String staticField = "静态字段";
    private String instanceField = "实例字段";
    
    // 静态内部类
    static class StaticInner {
        public void show() {
            System.out.println("访问外部静态字段:" + staticField);
            // System.out.println(instanceField);  // 编译错误:不能访问实例字段
        }
    }
}

public class StaticInnerDemo {
    public static void main(String[] args) {
        // 创建静态内部类对象
        Outer.StaticInner inner = new Outer.StaticInner();
        inner.show();
    }
}

局部内部类

java
class Outer {
    public void method() {
        final int localVar = 10;  // 局部变量
        
        // 局部内部类
        class LocalInner {
            public void show() {
                System.out.println("局部变量:" + localVar);
            }
        }
        
        LocalInner inner = new LocalInner();
        inner.show();
    }
}

public class LocalInnerDemo {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}

匿名内部类

java
interface Greeting {
    void greet();
}

public class AnonymousInnerDemo {
    public static void main(String[] args) {
        // 匿名内部类:实现接口
        Greeting greeting = new Greeting() {
            @Override
            public void greet() {
                System.out.println("你好,匿名内部类!");
            }
        };
        greeting.greet();
        
        // 匿名内部类:作为方法参数
        sayHello(new Greeting() {
            @Override
            public void greet() {
                System.out.println("作为参数的匿名内部类");
            }
        });
        
        // Lambda 表达式(Java 8+)简化
        Greeting lambda = () -> System.out.println("Lambda 表达式");
        lambda.greet();
    }
    
    public static void sayHello(Greeting greeting) {
        greeting.greet();
    }
}

小结

本章我们学习了:

  • 继承:子类继承父类的属性和方法,使用 extends 关键字
  • 方法重写:子类重新定义父类的方法
  • 多态:同一行为具有不同表现形式
  • 抽象类:不能实例化,可以包含抽象方法
  • 接口:定义方法规范,支持多实现
  • final 关键字:表示不可改变
  • 内部类:定义在类内部的类

下一章,我们将学习 异常处理,了解 Java 的异常处理机制。