【JavaSE】一站式掌握Java面向对象编程:从类与对象到继承、多态、抽象与接口

目录

前言

一、类与对象:万物皆对象的起点

[1.1 面向对象 vs. 面向过程](#1.1 面向对象 vs. 面向过程)

[1.2 类的定义与实例化](#1.2 类的定义与实例化)

[1.3 构造方法与对象初始化](#1.3 构造方法与对象初始化)

[1.4 this引用与封装](#1.4 this引用与封装)

[1.5 static成员与代码块](#1.5 static成员与代码块)

二、继承与多态:构建层次与实现灵活

[2.1 继承:代码复用的基石](#2.1 继承:代码复用的基石)

[2.2 super关键字与构造方法链](#2.2 super关键字与构造方法链)

[2.3 多态:同一接口,多种实现](#2.3 多态:同一接口,多种实现)

[2.4 final关键字](#2.4 final关键字)

三、抽象类与接口:定义规范与实现分离

[3.1 抽象类:不完整的蓝图](#3.1 抽象类:不完整的蓝图)

[3.2 接口:纯粹的行为契约](#3.2 接口:纯粹的行为契约)

[3.3 抽象类 vs 接口:核心抉择](#3.3 抽象类 vs 接口:核心抉择)

[3.4 Object类:所有类的根](#3.4 Object类:所有类的根)

总结:构建面向对象的思维


前言

面向对象编程是Java的基石,理解其核心概念是成为合格Java开发者的必经之路。

面向对象编程(Object-Oriented Programming,OOP)是一种基于对象 的软件开发范式,它通过将现实世界中的实体抽象为程序中的类和对象,使代码更符合人类思维模式,更易于理解、扩展和维护。Java作为一门纯面向对象语言 ,其核心特性包括:封装、继承、多态。本文将系统性地讲解这些核心概念,并结合代码示例与图表,助你构建完整的Java面向对象知识体系。


一、类与对象:万物皆对象的起点

1.1 面向对象 vs. 面向过程

面向过程 关注的是步骤和流程,如同传统洗衣:浸泡、搓洗、漂洗、拧干,每一步都需要亲手完成。其代码结构常表现为一系列函数的调用。

面向对象 关注的是对象及其交互,如同现代洗衣:人、衣服、洗衣机、洗衣粉四个对象通过交互完成任务。开发者更关注对象能提供什么服务,而非其内部如何实现。

java 复制代码
// 面向过程的"洗衣服"
void washClothes() {
    soak();   // 浸泡
    scrub();  // 搓洗
    rinse();  // 漂洗
    wring();  // 拧干
}

// 面向对象的"洗衣服"
Person person = new Person();
WashingMachine machine = new WashingMachine();
Detergent detergent = new Detergent();
Clothes clothes = new Clothes();

person.load(clothes, machine);
person.add(detergent, machine);
machine.start();

核心差异 :面向过程是动词思维 (如何做),面向对象是名词思维 (谁来做)。后者通过封装隐藏了实现细节,提高了代码的模块化和复用性。

1.2 类的定义与实例化

是对象的蓝图或模板,用于描述一类实体的属性 (成员变量)和行为 (成员方法)。它是一种自定义的数据类型

java 复制代码
// 定义一个"学生"类
public class Student {
    // 成员变量(属性):描述状态
    public String name;
    public String gender;
    public int age;
    public double score;

    // 成员方法(行为):描述功能
    public void attendClass() {
        System.out.println(name + "正在上课");
    }
    public void doHomework() {
        System.out.println(name + "正在写作业");
    }
}

对象 是类的具体实例,是内存中根据类模板创建的实体。使用 new 关键字进行实例化

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 实例化对象
        Student student1 = new Student();
        // 访问和设置属性
        student1.name = "张三";
        student1.age = 20;
        // 调用方法
        student1.attendClass();
    }
}

内存视角:类定义本身不占数据空间(如同建筑设计图),而每个对象都在堆内存中拥有独立的存储区域,存放各自的属性值。

1.3 构造方法与对象初始化

构造方法 是一种特殊的成员方法,用于在创建对象时初始化其成员变量。其名称必须与类名相同,且无返回值类型。

java 复制代码
public class Student {
    public String name;
    public int age;

    // 构造方法
    public Student(String initName, int initAge) {
        name = initName; // 初始化
        age = initAge;
        System.out.println("学生对象被创建");
    }
}

// 使用构造方法创建对象
Student stu = new Student("李四", 22);

Java对象初始化遵循特定顺序:

  1. 为对象分配内存,成员变量赋予默认值(0, false, null等)。

  2. 执行显式初始化(在声明时赋值)。

  3. 执行构造代码块

  4. 执行构造方法中的代码。

1.4 this引用与封装

this 关键字代表当前对象的引用,用于在成员方法或构造方法中,区分同名的局部变量和成员变量。

java 复制代码
public class Student {
    private String name;
    public void setName(String name) {
        this.name = name; // this.name指成员变量,name指形参
    }
}

封装 是OOP的第一大特性,它将数据(属性)和操作数据的方法(行为)绑定在一起,并隐藏内部实现细节,仅通过公共接口与外界交互。

java 复制代码
public class BankAccount {
    // 私有化成员变量,隐藏数据
    private double balance;
    private String password;

    // 提供公共方法作为访问接口
    public double getBalance(String inputPwd) {
        if (verifyPassword(inputPwd)) {
            return balance;
        }
        return -1; // 或抛出异常
    }
    private boolean verifyPassword(String input) {
        // 内部验证逻辑,对外不可见
        return this.password.equals(input);
    }
}

访问权限修饰符是实现封装的关键:

修饰符 同类 同包 子类 不同包
private
默认
protected
public

封装的意义

  1. 安全性:防止外部代码随意修改敏感数据。

  2. 易用性:使用者无需了解复杂内部逻辑,只需调用简单接口。

  3. 可维护性:内部实现修改不影响外部调用。

1.5 static成员与代码块

static 修饰的成员(变量或方法)属于类本身,而非某个特定对象。它们在类加载时初始化,被所有对象共享。

java 复制代码
public class Student {
    private String name;
    // 静态成员变量:所有学生共享的教室
    public static String classroom = "101教室";
    // 静态成员方法:可通过类名直接调用
    public static void printSchoolRule() {
        System.out.println("遵守校规");
        // System.out.println(name); // 错误!静态方法中不能直接访问非静态成员
    }
}
// 使用
System.out.println(Student.classroom);
Student.printSchoolRule();

代码块用于组织代码,分为:

  • 实例代码块:每次创建对象时执行,用于初始化实例成员。

  • 静态代码块 :在类首次加载时执行且仅执行一次,用于初始化静态成员。

java 复制代码
public class Example {
    static {
        System.out.println("静态代码块执行");
    }
    {
        System.out.println("实例代码块执行");
    }
    public Example() {
        System.out.println("构造方法执行");
    }
}

二、继承与多态:构建层次与实现灵活

2.1 继承:代码复用的基石

继承 允许一个类(子类/派生类)基于另一个类(父类/基类)来构建,复用其属性和方法,并可进行扩展。这体现了"is-a"的关系(例如,狗是一种动物)。

java 复制代码
// 父类:动物
class Animal {
    String name;
    int age;
    public void eat() {
        System.out.println(name + "正在吃饭");
    }
}
// 子类:狗 继承自动物
class Dog extends Animal {
    // 继承了name, age属性和eat()方法
    public void bark() {
        System.out.println(name + "汪汪叫"); // 可直接使用父类属性
    }
}

继承的优势

  1. 代码复用:消除重复代码。

  2. 逻辑清晰:建立清晰的类层次结构。

  3. 便于扩展:子类可添加新功能或重写父类功能。

2.2 super关键字与构造方法链

super 用于在子类中访问父类的成员(变量、方法或构造方法)。

java 复制代码
class Animal {
    String name = "动物";
}
class Dog extends Animal {
    String name = "狗";
    public void printName() {
        System.out.println(name);      // 输出"狗"(子类属性)
        System.out.println(super.name); // 输出"动物"(父类属性)
    }
}

构造方法的继承链 :创建子类对象时,必须先初始化父类部分

  • 子类构造方法默认首行会隐式调用 super()(父类无参构造)。

  • 若父类没有无参构造,子类必须显式调用 super(...) 并匹配父类构造方法的参数。

java 复制代码
class Animal {
    public Animal(String name) { /* ... */ }
}
class Dog extends Animal {
    public Dog(String name) {
        super(name); // 必须显式调用,且在第一行
        // 子类自己的初始化
    }
}

2.3 多态:同一接口,多种实现

多态 指同一操作作用于不同对象,可以产生不同的行为。在Java中主要通过方法重写父类引用指向子类对象来实现。

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("喵喵"); }
}

// 多态的应用
public class Test {
    public static void animalSound(Animal a) { // 父类引用作形参
        a.makeSound(); // 运行时确定调用哪个子类的方法
    }
    public static void main(String[] args) {
        Animal myDog = new Dog(); // 向上转型
        Animal myCat = new Cat();
        animalSound(myDog); // 输出"汪汪"
        animalSound(myCat); // 输出"喵喵"
    }
}

方法重写规则

  1. 方法名、参数列表必须完全相同。

  2. 返回值类型可以相同或是父类返回值的子类(协变返回类型)。

  3. 访问权限不能比父类更严格。

  4. 不能重写 private, static, final 方法。

重写(Override) vs 重载(Overload)

特性 重写 (Override) 重载 (Overload)
发生范围 父子类之间 同一个类内部
方法签名 必须相同 必须不同(参数类型、个数、顺序)
返回类型 可相同或协变 可修改
访问权限 不能更严格 可修改
作用 实现多态 提供同一功能的不同版本

2.4 final关键字

final 用于声明不可改变的实体:

  • final 变量:常量,值不可修改。

  • final 方法:不可被子类重写。

  • final 类:不可被继承(如 String 类)。


三、抽象类与接口:定义规范与实现分离

3.1 抽象类:不完整的蓝图

抽象类abstract 修饰,用于表示一种概念或框架 ,它可能包含未实现的抽象方法(仅有声明,无方法体)。

java 复制代码
// 抽象类:图形
abstract class Shape {
    protected double area; // 属性
    // 抽象方法:计算面积,由子类实现
    public abstract void calcArea();
    // 普通方法
    public double getArea() {
        return area;
    }
}
// 具体子类:圆
class Circle extends Shape {
    private double radius;
    public Circle(double r) { this.radius = r; }
    @Override // 必须实现抽象方法
    public void calcArea() {
        area = Math.PI * radius * radius;
    }
}

抽象类特性

  1. 不能直接实例化。

  2. 可以包含构造方法(供子类调用)、成员变量、普通方法和抽象方法。

  3. 子类继承抽象类后,必须实现所有抽象方法,除非子类也是抽象类。

3.2 接口:纯粹的行为契约

接口interface 定义,是一组完全抽象的公共行为规范。它定义类"能做什么",而不关心"怎么做"。

java 复制代码
// 接口:USB设备
public interface USB {
    // 默认 public static final
    String VERSION = "3.0";
    // 默认 public abstract
    void openDevice();
    void closeDevice();
}
// 实现类:鼠标
public class Mouse implements USB {
    @Override
    public void openDevice() { System.out.println("打开鼠标"); }
    @Override
    public void closeDevice() { System.out.println("关闭鼠标"); }
    public void click() { System.out.println("鼠标点击"); } // 自有方法
}

接口特性(Java 8+):

  1. 方法默认是 public abstract

  2. 变量默认是 public static final

  3. 不能有构造方法实例代码块

  4. Java 8起支持 default 方法(有默认实现)和 static 方法。

  5. Java 9起支持 private 方法。

3.3 抽象类 vs 接口:核心抉择

维度 抽象类 (Abstract Class) 接口 (Interface)
设计理念 是什么 (is-a),定义共性模板 能做什么 (has-a),定义行为契约
成员变量 无限制 只能是 public static final 常量
构造方法
方法实现 可有具体方法 Java 8前全抽象,8后可有 default/static 方法
继承关系 单继承 多实现
使用场景 为相关类提供通用基类,包含状态(字段) 定义跨继承树的不同类的共同能力

选择原则

  • 需要定义模板 ,包含共享状态或代码 时,用抽象类

  • 需要定义行为规范 ,且不关心实现者是谁时,用接口

  • 现代Java开发中,倾向于优先使用接口 ,组合使用 default 方法,以获得更大的灵活性。

3.4 Object类:所有类的根

Java中,所有类都直接或间接继承自 Object 类。它提供了一些通用方法:

  • toString(): 返回对象的字符串表示。建议重写以提供有意义的输出。

  • equals(Object obj): 判断对象内容是否相等。比较内容时必须重写== 比较引用地址)。

  • hashCode(): 返回对象的哈希码。重写 equals 时通常也要重写 hashCode,以保证一致性。

  • getClass(): 返回对象的运行时类。

  • clone(): 创建并返回对象的副本(需实现 Cloneable 接口)。


总结:构建面向对象的思维

面向对象编程的核心在于通过对象模拟现实,通过交互解决问题。掌握以下思维模型至关重要:

  1. 抽象思维:从具体事物中提取共同属性和行为,形成类。

  2. 封装思维:隐藏内部细节,暴露必要接口,构建高内聚、低耦合的模块。

  3. 继承思维:识别类之间的"is-a"关系,构建清晰的层次结构,实现代码复用。

  4. 多态思维:基于父类引用操作子类对象,编写更通用、更灵活的代码。

  5. 接口思维:面向契约编程,定义"能做什么",而非"是什么",提高系统的可扩展性和可替换性。

相关推荐
Rubin智造社2 小时前
见路不走:从《天幕红尘》读懂2026年的创新密码
android·开发语言·kotlin
皮蛋sol周2 小时前
嵌入式学习数据结构(二)双向链表 内核链表
linux·数据结构·学习·嵌入式·arm·双向链表
你的冰西瓜2 小时前
C++中的map容器详解
开发语言·c++·stl
leo__5202 小时前
基于C#实现软件注册码注册机制
开发语言·c#·哈希算法
小园子的小菜2 小时前
Spring事务失效9大场景(Java面试高频)
java·spring·面试
满栀5852 小时前
插件轮播图制作
开发语言·前端·javascript·jquery
向前V2 小时前
Flutter for OpenHarmony数独游戏App实战:胜利弹窗
java·flutter·游戏
苦藤新鸡2 小时前
16.求数组除了当前元素的所有乘积
算法·leetcode·动态规划
WilliamHu.2 小时前
A2A协议
java·数据结构·算法