Skip to content

面向对象基础

前置知识

在阅读本章前,你需要了解Java的基本语法,比如变量、数据类型、方法定义和调用。

为什么需要面向对象?

想象一下,你刚入职一家软件公司,接手一个巨大的程序,这个程序到处都是庞大而重复的代码,维护起来让人头疼。你可能会问:“有没有一种方法,让代码看起来更像现实世界的东西,更有条理,也更容易扩展和维护?”这正是**面向对象编程(OOP)**诞生的初衷。

我们这节课会从最基础的“类和对象”开始,帮你理清这门编程范式的核心概念。别担心,我会陪你一步步来,逐渐揭开OOP神秘的面纱。


什么是类与对象?

简单定义(人话版)

就像蓝图或模板,是用来描述一类事物的特点和行为的;对象则是根据这个蓝图“造”出来的实体,每个对象都有自己的状态。

举个家常例子:

  • “汽车”是类,
  • “我的那辆红色本田”就是对象。

为什么需要类与对象?

之前写程序时,你可能直接用变量和函数拼凑逻辑,会发现代码很难组织和复用。类和对象让你能把数据(属性)和操作数据的代码(方法)放在一起,模拟真实世界的“事物”,更符合我们直觉。


基础代码示例1:定义一个简单类和创建对象

java
// 描述一个简单汽车类
public class Car {
    // 属性:汽车颜色和品牌
    String color;
    String brand;

    // 方法:显示汽车信息
    public void showInfo() {
        System.out.println("这是一辆 " + color + " 色的 " + brand);
    }

    public static void main(String[] args) {
        // 创建Car对象
        Car myCar = new Car();
        myCar.color = "红";
        myCar.brand = "本田";

        // 调用对象的方法
        myCar.showInfo();
    }
}

这段代码做了什么:

  1. 定义了Car类,里面有两个属性colorbrand,还有一个展示汽车信息的方法。
  2. main方法里,我们“造”了一个Car对象,叫myCar
  3. 为对象赋了颜色和品牌,接着调用它的方法显示信息。

封装:保护数据的“小房间”

简单定义

直接让对象的属性“裸奔”很危险,你可能想给别人看的只能是方法,不允许直接修改重要属性。封装就是用private关键字隐藏属性,只通过公开方法访问。

为什么要封装?

保护数据安全是编程中一个基本原则。就像你不希望别人随便翻你的日记一样,封装让你控制外界对属性的访问,避免程序出现难以追踪的错误。


代码示例2:用封装保护属性

java
public class Person {
    // 私有属性
    private String name;
    private int age;

    // 构造方法,方便创建对象时初始化属性
    public Person(String name, int age) {
        this.name = name;  // 这里的this指当前对象
        this.age = age;
    }

    // 公开的getter方法,允许别人读取name
    public String getName() {
        return name;
    }

    // 公开的setter方法,允许别人修改age,但可以做检查
    public void setAge(int age) {
        if(age > 0) {
            this.age = age;
        } else {
            System.out.println("年龄必须是正数!");
        }
    }

    // 显示个人信息的方法
    public void showInfo() {
        System.out.println(name + ",年龄:" + age);
    }

    public static void main(String[] args) {
        Person person = new Person("小明", 20);
        person.showInfo();

        person.setAge(-5);  // 错误,年龄不能是负数
        person.setAge(25);  // 正确
        person.showInfo();
    }
}

这段代码做了什么:

  1. 使用private隐藏nameage属性。
  2. 通过构造方法初始化对象。
  3. 公开getNamesetAge方法控制属性访问,其中setAge带了简单的有效性检查。
  4. main方法测试了封装后的安全访问。

构造方法和this关键字:给对象“穿衣服”和“指身份”

什么是构造方法?

构造方法是一种特殊的方法,当你用new创建对象时会自动执行,为对象“穿上”正确的属性值。它名字和类名一样,没有返回值。

this关键字有什么用?

this指当前对象本身,解决“变量遮蔽”问题。比如参数名和属性名一样时,写this.name指的是对象的属性,而不是局部变量。


代码示例3:复杂构造方法和this演示

java
public class Book {
    private String title;
    private String author;
    private int pages;

    // 多个构造方法,通过重载支持不同初始化方式
    public Book(String title, String author) {
        this.title = title;  // this指当前对象的title属性
        this.author = author;
        this.pages = 0;      // 默认页数是0
    }

    public Book(String title, String author, int pages) {
        this(title, author); // 调用另一个构造方法,复用代码
        this.pages = pages;
    }

    public void showInfo() {
        System.out.println("书名:" + title + ", 作者:" + author + ", 页数:" + pages);
    }

    public static void main(String[] args) {
        Book book1 = new Book("Java 核心技术", "Cay S. Horstmann");
        Book book2 = new Book("Effective Java", "Joshua Bloch", 416);

        book1.showInfo();
        book2.showInfo();
    }
}

这段代码做了什么:

  1. 定义了含有属性和两个构造方法的Book类,支持不同参数初始化。
  2. 通过this(...)实现构造方法间的调用,避免重复代码。
  3. 体现了this关键字在属性赋值和构造调用中的应用。
  4. 测试了不同构造方式创建的对象并打印信息。

对象创建过程概览

简单理解:当执行new ClassName()时:

  1. JVM分配内存给新对象。
  2. 初始化默认值(数值为0,布尔为false,对象为null)。
  3. 调用构造方法,执行代码给属性赋初始值。
  4. 返回对象引用。

这一步很关键,也是你理解后续OOP高级特性(如继承、多态)的基础。


⚠️ 常见陷阱

  • 构造方法和普通方法不可重载返回类型,只能通过参数列表区分。
  • 使用this引用对象属性时,确保没有写成赋值反了(比如name = this.name; 是错的)。
  • 直接暴露public属性容易造成意外修改,养成封装的习惯,提升代码健壮性。
  • 构造方法中的代码执行顺序非常重要,初始化顺序和逻辑错误可能导致bug难排。

实战建议

在实际项目中,我发现:

  • 先设计好类的属性和责任,切忌一开始追求复杂功能而写一大堆混乱代码。
  • 构造方法中应该尽量保持简单,复杂逻辑放到其他初始化方法或用工厂模式处理。
  • 面向对象的核心是建模,花时间思考哪个类应该负责哪些行为。
  • 封装不仅保护了数据,也让类的使用者更容易理解和使用你的代码。

小结

  • 类是抽象模板,对象是具体实例。
  • 封装用private隐藏数据,通过gettersetter控制访问。
  • 构造方法用于初始化对象,this关键字指当前对象并解决变量名冲突。
  • 创建对象时,JVM会分配内存、执行构造方法,确保对象准备好被使用。

这些基础知识是你面向对象编程的地基,牢固它,才能搭建出更复杂灵活的软件结构。


延伸思考

  • 当一个类中属性非常多时,构造方法如何设计才能不让代码臃肿?
  • 你能想到除了构造方法初始化对象外,还有哪些创建和初始化对象的方式?
  • 你有没有遇到过变量名和参数名冲突没有用this导致的奇怪bug?可以试着模拟一下。

如果你准备好了,我们下一章会带你深入理解继承和多态,这可是面向对象真正的魔法——让代码变得灵活又强大。我们一起走下去!