Java面向对象编程:从基础到高级的全面指南

Java面向对象编程:从基础到高级的全面指南

前言

面向对象编程(OOP)是Java语言的核心特性。本文将系统讲解Java面向对象的基础和高级特性,帮助读者构建完整的知识体系。所有示例代码都经过验证,适合大二学生理解与实践。


一、面向对象基础

1.1 面向对象基本概念

核心思想:将现实世界的事物抽象为对象,通过对象之间的交互来解决问题

  • 对象:现实事物的抽象(如:学生张三)

    • 具有状态(成员变量)和行为(方法)
    • 在内存中占用独立空间
  • :对象的模板(如:Student类)

    • 定义对象的属性(成员变量)和行为(方法)
    • 类与对象的关系:类是设计图,对象是根据设计图建造的房子

三大特征

  • 封装:隐藏对象内部实现细节

    • 优点:提高安全性、降低耦合度
    • 实现方式:访问控制修饰符
  • 继承:代码复用与扩展

    • 子类自动拥有父类非private成员
    • 单继承特性:Java类只能有一个直接父类
  • 多态:同一操作作用于不同对象产生不同行为

    • 必要条件:继承、方法重写、父类引用指向子类对象

1.2 类与对象

类结构

[访问修饰符] class 类名 {
    // 成员变量(描述状态)
    // 构造方法(初始化对象)
    // 成员方法(描述行为)
}

内存图解

栈内存:存储对象引用
堆内存:存储对象实例
方法区:存储类信息

示例代码

// 类定义
public class Student {
    // 成员变量(属性)
    private String name;  // 状态
    private int age;
    
    // 成员方法(行为)
    public void study(String subject) {
        System.out.println(name + "正在学习" + subject);
    }
}

// 创建对象(实例化)
Student stu = new Student();  // new关键字触发内存分配

1.3 访问权限

访问控制本质:控制类的可见性和修改范围,实现封装特性

修饰符 类内 包内 子类 任意位置 使用场景
private 内部实现细节保护
default 包内共享
protected 子类继承访问
public 对外提供的公共服务

选择原则

  • 成员变量优先用private
  • 方法根据使用范围选择
  • 类一般用public或default

1.4 类的封装

封装的意义

  1. 防止不合理赋值(如年龄设为-20)
  2. 隐藏内部存储方式(如日期可用long型存储)
  3. 方便后续修改实现

标准实现

public class BankAccount {
    private String accountNumber;  // 私有化字段
    private double balance;
    
    // 对外暴露的存取方法
    public double getBalance() {
        return balance;
    }
    
    public void deposit(double amount) {
        if(amount > 0) {
            balance += amount;
        }
    }
    
    public void withdraw(double amount) {
        if(amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }
}

1.5 构造方法

核心作用:对象初始化,确保对象创建后处于合法状态

特点

  • 方法名与类名相同
  • 没有返回值类型
  • 可以重载(创建多个不同参数的构造方法)

内存初始化流程

  1. 为对象分配内存空间
  2. 执行属性默认初始化(0/false/null)
  3. 执行显式初始化(成员变量直接赋值)
  4. 执行构造方法代码

示例

public class Book {
    private String title;
    private String author;
    
    // 默认构造方法(建议保留)
    public Book() {
        this("未知书名", "未知作者");
    }
    
    // 全参构造方法
    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
}

1.6 this关键字

三种用法

  1. 解决成员变量与局部变量同名问题
  2. 调用本类其他构造方法(必须位于构造方法首行)
  3. 作为参数传递当前对象

内存原理

  • 每个对象都有一个隐含的this引用
  • this保存当前对象的内存地址
  • 通过this可以访问该对象的所有成员
public class Point {
    int x;
    int y;
    
    public Point(int x, int y) {
        this.x = x;  // 区分同名变量
        this.y = y;
    }
    
    public Point() {
        this(0, 0);  // 调用其他构造方法
    }
    
    public Point getThis() {
        return this;  // 返回当前对象
    }
}

1.7 static关键字

核心特性

  • 属于类而不是实例
  • 在类加载时初始化
  • 被所有实例共享

使用场景

  1. 工具类方法(如Math.sqrt())
  2. 共享数据(如在线人数统计)
  3. 常量定义(static final)

内存分配

  • 静态成员存储在方法区的静态存储区
  • 实例成员存储在堆内存的对象中
public class AppConfig {
    // 静态常量
    public static final String VERSION = "1.0";
    
    // 静态变量
    private static int accessCount = 0;
    
    // 静态代码块(类加载时执行)
    static {
        System.out.println("初始化配置...");
    }
    
    // 静态方法
    public static void recordAccess() {
        accessCount++;
    }
}

二、面向对象高级

2.1 类的继承

继承的本质:建立类与类之间的"is-a"关系(如Cat is an Animal)

优势

  • 代码复用:子类自动获得父类功能
  • 扩展灵活:子类可以添加新功能
  • 多态基础:统一处理不同子类对象

继承限制

  • Java单继承:一个类只能有一个直接父类
  • 构造方法不可继承
  • private成员不可直接访问
class Animal {
    String name;
    
    void eat() {
        System.out.println(name + "正在进食");
    }
}

class Cat extends Animal {
    void climbTree() {
        System.out.println(name + "在爬树");  // 继承父类name
    }
}

2.2 方法重写(Override)

与重载(Overload)的区别

方法重写 方法重载
所在类 父子类之间 同一个类中
方法名 相同 相同
参数列表 相同 不同
返回类型 相同或是子类 可不同
访问权限 不能比父类更严格 无关
异常类型 不能抛出更宽泛的检查型异常 无关

@Override注解的作用

  • 帮助编译器检查是否正确重写
  • 提高代码可读性
  • 防止意外重载
class Animal {
    protected void move() {
        System.out.println("动物移动");
    }
}

class Bird extends Animal {
    @Override  // 显式声明重写
    public void move() {  // 扩大访问权限
        System.out.println("鸟儿飞翔");
    }
}

2.3 Object类

重要方法解析

  1. toString()

    • 默认返回:类名@哈希码
    • 重写建议:返回有意义的对象描述
    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
    
  2. equals()

    • 默认实现:== 比较(判断是否为同一对象)
    • 重写规范:
      • 自反性:x.equals(x) == true
      • 对称性:x.equals(y) == y.equals(x)
      • 传递性:x=y且y=z → x=z
      • 一致性:多次调用结果相同
      • 非空性:x.equals(null) == false
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && 
               Objects.equals(name, student.name);
    }
    
  3. hashCode()

    • 与equals()的契约:相等对象必须有相同哈希码
    • 重写建议:使用相同字段生成哈希码

2.4 super关键字

三种用法

  1. 访问父类成员变量/方法
  2. 调用父类构造方法(必须位于子类构造方法首行)
  3. 在泛型中指定父类型
class Employee {
    String name = "员工";
    
    public Employee(String name) {
        this.name = name;
    }
}

class Manager extends Employee {
    String name = "经理";
    
    public Manager() {
        super("默认经理");  // 调用父类构造
    }
    
    void showNames() {
        System.out.println(super.name);  // 访问父类属性
        System.out.println(this.name);  // 访问子类属性
    }
}

2.5 final关键字

三种应用场景

  1. final类:禁止继承(如String类)

    public final class Constants {
        // 工具类设计
    }
    
  2. final方法:禁止子类重写

    public class Parent {
        public final void importantMethod() {
            // 核心算法实现
        }
    }
    
  3. final变量:只能赋值一次

    // 基本类型:值不可变
    final int MAX_VALUE = 100;
    
    // 引用类型:引用不可变
    final List<String> NAMES = new ArrayList<>();
    NAMES.add("Tom");  // 允许,修改的是对象内容
    // NAMES = new ArrayList<>();  // 编译错误
    

2.6 抽象类

核心特征

  • 用abstract修饰
  • 可以包含抽象方法(无实现)
  • 不能直接实例化
  • 子类必须实现所有抽象方法(除非子类也是抽象类)

适用场景

  • 定义通用模板
  • 规范子类必须实现的方法
  • 包含具体方法和抽象方法的混合
abstract class Graphic {
    // 抽象方法
    public abstract double area();
    
    // 具体方法
    public void printArea() {
        System.out.println("面积:" + area());
    }
}

class Circle extends Graphic {
    private double radius;
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

2.7 接口

演进历程

  • Java 7:只能有抽象方法和常量
  • Java 8:加入默认方法和静态方法
  • Java 9:加入私有方法

核心特性

  • 用interface定义
  • 支持多实现(解决单继承局限)
  • 默认方法允许接口演化
  • 接口间可以多继承

与抽象类的区别

抽象类 接口
构造方法
成员变量 任意类型 默认public static final
方法实现 可以有具体方法 Java8+支持默认方法
继承方式 单继承 多实现
设计目的 代码复用 定义行为规范
// 接口定义
interface Flyable {
    // 常量
    double MAX_SPEED = 1000;  // 默认public static final
    
    // 抽象方法
    void takeoff();          // 默认public abstract
    
    // 默认方法
    default void emergencyLanding() {
        System.out.println("紧急迫降");
    }
}

// 接口继承
interface AdvancedFlyable extends Flyable {
    void supersonicFly();
}

// 类实现
class Airplane implements AdvancedFlyable {
    @Override
    public void takeoff() {
        System.out.println("滑行起飞");
    }
    
    @Override
    public void supersonicFly() {
        System.out.println("超音速飞行");
    }
}

2.8 对象类型转换

转型规则

  • 向上转型(自动):子类→父类
  • 向下转型(强制):父类→子类(需通过instanceof检查)

转型应用场景

  • 使用通用父类处理不同子类
  • 访问子类特有方法
Animal animal = new Cat();  // 向上转型
animal.eat();  // 调用父类方法

if(animal instanceof Cat) {
    Cat cat = (Cat)animal;  // 向下转型
    cat.catchMouse();  // 调用子类特有方法
}

2.9 多态

实现机制

  1. 编译时多态:方法重载
  2. 运行时多态:方法重写 + 向上转型

JVM实现原理

  • 方法调用指令:
    • invokestatic:调用静态方法
    • invokespecial:调用构造方法、私有方法、父类方法
    • invokevirtual:调用实例方法(多态实现基础)
    • invokeinterface:调用接口方法

多态优势

  • 提高代码扩展性
  • 降低模块耦合度
  • 增强程序可维护性
class Animal {
    public void move() {
        System.out.println("动物移动");
    }
}

class Fish extends Animal {
    @Override
    public void move() {
        System.out.println("鱼儿游动");
    }
}

class Bird extends Animal {
    @Override
    public void move() {
        System.out.println("鸟儿飞翔");
    }
}

// 测试类
public class Test {
    public static void main(String[] args) {
        Animal[] animals = new Animal[3];
        animals[0] = new Animal();
        animals[1] = new Fish();
        animals[2] = new Bird();
        
        for(Animal a : animals) {
            a.move();  // 同一方法不同表现
        }
    }
}

2.10 内部类

四大类型

  1. 成员内部类:作为外部类成员
  2. 局部内部类:定义在方法内
  3. 匿名内部类:没有类名的即时实现
  4. 静态内部类:static修饰的内部类

使用场景

  • 封装仅被一个类使用的功能
  • 实现多重继承
  • 事件处理(如GUI编程)
// 成员内部类
class Outer {
    private int num = 10;
    
    class Inner {
        void show() {
            System.out.println(num);  // 直接访问外部类私有成员
        }
    }
}

// 匿名内部类
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("按钮被点击");
    }
});

// 静态内部类
class Map {
    static class Entry {
        // 不依赖外部类实例
    }
}

三、综合应用案例

动物管理系统

abstract class Animal {
    private String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public abstract void sound();
    
    public String getName() {
        return name;
    }
}

interface Swimmable {
    void swim();
}

class Dolphin extends Animal implements Swimmable {
    public Dolphin(String name) {
        super(name);
    }
    
    @Override
    public void sound() {
        System.out.println("超声波");
    }
    
    @Override
    public void swim() {
        System.out.println(getName() + "在海中遨游");
    }
}

public class Zoo {
    public static void main(String[] args) {
        Animal animal = new Dolphin("泡泡");
        animal.sound();
        
        if(animal instanceof Swimmable) {
            ((Swimmable)animal).swim();
        }
    }
}

你可能感兴趣的:(java,开发语言)