教程中心 / Java教程 / 面向对象编程

面向对象编程 - 类与对象

25分钟 核心概念

引言:什么是面向对象编程?

面向对象编程(Object-Oriented Programming,OOP)是一种程序设计思想,它将程序中的数据和操作数据的方法组织在一起,形成"对象"。

想象一下现实世界:

  • 汽车是一种"类",具体的某辆汽车(如车牌号"京A12345")是一个"对象"
  • 学生是一种"类",具体某个学生"张三"是一个"对象"
  • 银行账户是一种"类",具体某个账户是一个"对象"

面向对象的三大特征:

  • 封装(Encapsulation):把数据和方法包装在一起
  • 继承(Inheritance):类之间的关系
  • 多态(Polymorphism):同一操作不同表现

类的定义

类(Class)是对象的模板或蓝图,它定义了对象应该具有的属性和方法。

类的基本结构

[访问修饰符] class 类名 {
    // 属性(字段)
    // 方法
}

一个完整的类示例

public class Student {
    // ========== 属性(特征)==========

    private String name;     // 姓名
    private int age;         // 年龄
    private int score;       // 成绩

    // ========== 构造方法 ==========

    public Student() {
    }

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    // ========== 方法(行为)==========

    public void study() {
        System.out.println(name + "正在学习...");
    }

    public void exam() {
        System.out.println(name + "正在考试...");
        score = score - 10;
        System.out.println(name + "考试结束,成绩:" + score);
    }

    // ========== Getter和Setter ==========

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + ", score=" + score + "}";
    }
}

对象的创建和使用

创建对象

public class Main {
    public static void main(String[] args) {
        // 使用new关键字创建对象
        Student student = new Student();

        // 调用方法
        student.setName("张三");
        student.setAge(18);
        student.setScore(100);

        student.study();
        student.exam();

        System.out.println(student);
    }
}

对象的内存模型

对象在内存中的存储

Student student = new Student();
student.setName("张三");

┌─────────────────────────────────┐
│           堆内存(Heap)         │
│  ┌─────────────────────────┐    │
│  │      Student对象         │    │
│  │  name: "张三"            │    │
│  │  age: 18                │    │
│  │  score: 100             │    │
│  └─────────────────────────┘    │
└─────────────────────────────────┘
           ↑
           │
    student引用变量
    (存储在栈内存中)

封装

封装是面向对象的第一大特征,它将数据和操作数据的方法包装在一起,对外提供接口,隐藏内部实现细节。

为什么要封装?

数据保护:防止外部随意修改重要数据
隐藏复杂性:外部不需要知道内部如何实现
易于维护:修改内部实现不影响外部使用

封装的实现:访问修饰符

修饰符同类同包子类任意位置
private
(默认)
protected
public

封装的实践

public class Person {
    // 使用private隐藏数据
    private String name;
    private int age;

    // 使用public方法提供访问接口
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    // 在setter中加入验证逻辑
    public void setAge(int age) {
        if (age < 0 || age > 150) {
            System.out.println("年龄不合法!");
            return;
        }
        this.age = age;
    }
}

构造方法

构造方法是创建对象时调用的特殊方法,用于初始化对象。

构造方法的特点

方法名与类名相同
没有返回类型(连void都没有)
创建对象时自动调用

无参构造方法

public class Dog {
    private String name;

    // 如果不写构造方法,编译器会自动提供一个默认的无参构造方法
    public Dog() {
        System.out.println("无参构造方法被调用");
    }
}

// 使用
Dog dog = new Dog();  // 调用无参构造方法

带参构造方法

public class Dog {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

// 使用
Dog dog = new Dog("旺财", 3);

构造方法重载

public class Dog {
    private String name;
    private int age;
    private String color;

    // 构造方法重载
    public Dog() {
    }

    public Dog(String name) {
        this.name = name;
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
}

this关键字

this关键字指向当前对象,用于区分成员变量和局部变量。

public class Person {
    private String name;

    public Person(String name) {
        // this.name 表示对象的成员变量
        // name 表示构造方法的参数(局部变量)
        this.name = name;
    }

    public void setName(String name) {
        // 同样用this区分
        this.name = name;
    }
}

重要规则:如果定义了带参构造方法,编译器就不会自动提供无参构造方法。如果需要,确保手动添加无参构造方法。

static关键字

static修饰的成员属于类,不属于对象。

静态变量(类变量)

public class Student {
    private String name;
    private static int studentCount = 0;  // 所有学生对象共享

    public Student(String name) {
        this.name = name;
        studentCount++;  // 每创建一个学生,对象计数加1
    }

    public static int getStudentCount() {
        return studentCount;
    }
}

// 使用
Student s1 = new Student("张三");
Student s2 = new Student("李四");
System.out.println(Student.getStudentCount());  // 2

静态方法

public class MathHelper {
    public static int max(int a, int b) {
        return a > b ? a : b;
    }

    public static int min(int a, int b) {
        return a < b ? a : b;
    }
}

// 使用:不需要创建对象,直接类名.方法名调用
int max = MathHelper.max(10, 20);
int min = MathHelper.min(10, 20);

静态方法注意事项:

  • 静态方法只能访问静态成员,不能访问实例成员
  • 静态方法中不能使用this关键字
  • 调用时使用类名.方法名()或直接方法名()

代码规范与最佳实践

类命名规范

// 正确的类名命名
public class Student {}           // 名词,大写开头
public class UserAccount {}        // 多个单词驼峰命名
public class ArrayList {}         // 内部已存在,示例而已

// 错误的类名命名
public class student {}           // 应该大写开头
public class student_info {}      // 不应该用下划线

方法命名规范

public class User {
    // 正确的方法命名
    public void setName(String name) {}   // 驼峰命名
    public String getName() {}
    public void calculateTotalPrice() {}
    public boolean isActive() {}          // 布尔类型用is开头

    // 错误的命名
    public void SetName(String name) {}   // 不应该大写开头
}

小结

  • 是对象的模板,定义属性和方法;对象是类的实例
  • 封装通过private隐藏数据,通过public方法提供访问接口
  • 构造方法用于创建和初始化对象
  • this关键字指向当前对象,用于区分成员变量和局部变量
  • static修饰的成员属于类,所有对象共享
  • 访问修饰符控制可见性:private < 默认 < protected < public
☕ Java 在线代码编辑器
📝 运行结果