Java 面向对象:从思想到类与对象,真正迈入 OOP 的大门

学习日期:2026-06-03

难度:⭐⭐⭐ 进阶入门

一、为什么需要面向对象?

先回顾一下我们之前学的:流程控制、数组——这些都是面向过程的写法:关注"第一步做什么、第二步做什么"。

但现实世界不是这样的。你点外卖,不会去想"餐厅怎么炒菜、骑手怎么导航",你只关心有什么对象、对象能做什么

plaintext

9

1

2

3

面向过程:炒菜 → 打包 → 取餐 → 骑行 → 送达

面向对象:餐厅.做餐() → 骑手.配送() → 我.收餐()

面向过程像写菜谱,一步一步来;面向对象像导演安排演员,每个角色各司其职。

表格

对比 面向过程 面向对象
核心思想 以步骤为中心 以对象为中心
适合场景 简单脚本、小工具 大型系统、复杂业务
复用方式 函数调用 继承、组合
扩展性 改动影响大 改动局部化

二、面向对象三大特征(先有个概念)

这仨是 OOP 的灵魂,后面会逐个深入,今天先记住名字:

  1. 封装:把数据藏起来,只暴露必要的操作 → 安全、可控
  2. 继承:子类复用父类的代码 → 避免重复
  3. 多态:同一个方法,不同对象有不同的表现 → 灵活、可扩展

🎯 今天重点搞懂"类与对象",封装会顺带涉及,继承和多态后面专门学。

三、类与对象:图纸和房子的关系

3.1 一句话区分

  • 类(Class) :是设计图纸,描述一类事物有什么、能做什么
  • 对象(Object) :是根据图纸造出来的具体实例

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// 类 = 图纸

class Phone {

String brand; // 有什么:品牌

double price; // 有什么:价格

void call() { // 能做什么:打电话

System.out.println("用" + brand + "打电话");

}

}

// 对象 = 根据图纸造出来的真手机

Phone myPhone = new Phone();

myPhone.brand = "小米";

myPhone.call(); // 用小米打电话

plaintext

9

1

2

3

4

5

6

7

类(Phone) 对象1 对象2

┌──────────────┐ ┌──────────────┐ ┌──────────────┐

│ brand │ │ brand = "小米"│ │ brand = "苹果"│

│ price │ ──→ │ price = 2999 │ │ price = 8999 │

│ call() │ │ call() │ │ call() │

└──────────────┘ └──────────────┘ └──────────────┘

💡 一个类可以创建无数个对象,每个对象独立拥有自己的数据。

3.2 类的定义语法

java

99

1

2

3

4

5

6

7

8

9

10

class 类名 {

// 1. 成员变量(属性)—— 描述"有什么"

数据类型 变量名;

// 2. 成员方法(行为)—— 描述"能做什么"

返回值类型 方法名(参数列表) {

// 方法体

}

}

来个完整的例子:

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

class Student {

// 属性

String name;

int age;

String major;

// 行为

void study() {

System.out.println(name + "正在学习" + major);

}

void introduce() {

System.out.println("我叫" + name + ",今年" + age + "岁");

}

}

3.3 创建和使用对象

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public class Main {

public static void main(String[] args) {

// 创建对象:new 类名()

Student stu1 = new Student();

// 给属性赋值

stu1.name = "张三";

stu1.age = 20;

stu1.major = "计算机科学";

// 调用方法

stu1.introduce(); // 我叫张三,今年20岁

stu1.study(); // 张三正在学习计算机科学

// 再创建一个,互不影响

Student stu2 = new Student();

stu2.name = "李四";

stu2.age = 22;

stu2.introduce(); // 我叫李四,今年22岁

}

}

四、构造方法:对象的"出生证明"

4.1 什么是构造方法?

每次 new Student() 时调用的那个特殊方法,就是构造方法。它负责初始化对象。

特点:

  • 方法名和类名完全一致
  • 没有返回值类型(连 void 都不写)
  • 创建对象时自动调用,不能手动调

4.2 默认构造方法

如果你不写任何构造方法,Java 会偷偷给你加一个无参构造

java

9

1

2

3

4

5

6

7

class Student {

String name;

int age;

// 你没写,但 Java 默认存在:

// Student() { }

}

4.3 自定义构造方法

一旦你自己写了构造方法,默认的就没了!

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

class Student {

String name;

int age;

// 无参构造

Student() {

System.out.println("一个学生诞生了!");

}

// 有参构造:创建时直接赋值

Student(String n, int a) {

name = n;

age = a;

}

}

// 使用

Student stu1 = new Student(); // 调用无参构造

Student stu2 = new Student("王五", 21); // 调用有参构造

⚠️ 常见坑:如果你只写了有参构造,没写无参构造,那 new Student() 会报错!建议:写了有参构造时,顺手补一个无参构造。

五、this 关键字:指代"我自己"

5.1 解决命名冲突

当成员变量和局部变量同名时,用 this 区分:

java

99

1

2

3

4

5

6

7

8

9

10

class Student {

String name;

int age;

Student(String name, int age) {

this.name = name; // this.name = 成员变量,name = 参数

this.age = age;

}

}

💡 这是最常见用法,IDE 生成构造方法时自动带 this。

5.2 在构造方法中调用另一个构造方法

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

class Student {

String name;

int age;

String major;

Student(String name, int age) {

this.name = name;

this.age = age;

}

Student(String name, int age, String major) {

this(name, age); // 调用上面的两参构造

this.major = major; // 再额外设置 major

}

}

⚠️ this() 必须放在构造方法的第一行,否则编译报错。

六、封装:别让人随便动我的数据

6.1 问题在哪?

java

9

1

2

3

Student stu = new Student();

stu.age = -999; // 年龄设成负数?不合理但编译不报错!

成员变量直接暴露,任何人都能乱赋值——这不安全。

6.2 解决方案:private + getter/setter

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class Student {

private String name;

private int age; // 私有:外部不能直接访问

// getter:读取

public int getAge() {

return age;

}

// setter:写入(加校验)

public void setAge(int age) {

if (age < 0 || age > 150) {

System.out.println("年龄不合法!");

return;

}

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

使用:

java

9

1

2

3

4

5

Student stu = new Student();

stu.setAge(-999); // 年龄不合法!赋值失败

stu.setAge(20); // ✅ 合法

System.out.println(stu.getAge()); // 20

封装的原则:

  • 属性用 private 修饰
  • 对外提供 public 的 getter/setter
  • 在 setter 中做数据校验

表格

访问修饰符 同类 同包 不同包
private
默认(不写)
protected ✅(子类)
public

七、成员变量 vs 局部变量

表格

对比 成员变量 局部变量
位置 类中,方法外 方法内
默认值 有(0、null、false等) 无,必须先赋值才能用
作用域 整个类 从定义到方法结束
生命周期 对象创建到销毁 方法调用到结束

java

99

1

2

3

4

5

6

7

8

9

10

11

12

class Demo {

int a; // 成员变量,默认值0

void test() {

int b; // 局部变量,无默认值

// System.out.println(b); // ❌ 编译报错:可能未初始化

b = 10;

System.out.println(b); // ✅ 10

System.out.println(a); // ✅ 0(成员变量有默认值)

}

}

八、方法重载(Overload)

同一个类中,方法名相同、参数列表不同——这就是重载。

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

class Calculator {

int add(int a, int b) {

return a + b;

}

double add(double a, double b) { // 参数类型不同

return a + b;

}

int add(int a, int b, int c) { // 参数个数不同

return a + b + c;

}

}

重载规则:

  • ✅ 参数个数不同
  • ✅ 参数类型不同
  • ✅ 参数顺序不同
  • ❌ 仅返回值不同——不算重载,编译报错

💡 构造方法也可以重载,前面的 Student()Student(String, int) 就是。

九、static:属于类,不属于对象

9.1 静态变量——所有对象共享

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

class Student {

String name;

static String school = "清华大学"; // 静态变量:所有学生共享

Student(String name) {

this.name = name;

}

}

Student stu1 = new Student("张三");

Student stu2 = new Student("李四");

// 通过类名访问(推荐)

System.out.println(Student.school); // 清华大学

// 修改后所有人都能看到

Student.school = "北京大学";

System.out.println(stu1.school); // 北京大学

System.out.println(stu2.school); // 北京大学

9.2 静态方法——不依赖对象就能调用

java

9

1

2

3

4

5

6

7

8

9

class MathUtils {

static int max(int a, int b) {

return a > b ? a : b;

}

}

// 不需要 new 对象,直接用类名调用

int result = MathUtils.max(10, 20); // 20

⚠️ 静态方法不能直接访问非静态成员(因为没有对象实例):

java

9

1

2

3

4

5

6

7

class Demo {

int a = 10;

static void test() {

// System.out.println(a); // ❌ 编译报错!

}

}

9.3 什么时候用 static?

表格

场景 选择
每个对象各自拥有的数据 普通成员变量
所有对象共享的数据 static 变量
需要访问对象属性的方法 普通成员方法

工具类方法(不依赖对象状态) | static 方法 |

十、代码块:初始化的另一种方式

10.1 构造代码块

每次创建对象时都会执行,在构造方法之前运行:

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

class Student {

String name;

// 构造代码块

{

System.out.println("一个新的学生正在注册...");

}

Student() {

System.out.println("无参构造执行");

}

Student(String name) {

this.name = name;

System.out.println("有参构造执行");

}

}

// 无论调哪个构造方法,都会先执行构造代码块

new Student(); // 新的学生正在注册... → 无参构造执行

new Student("张三"); // 新的学生正在注册... → 有参构造执行

10.2 静态代码块

类加载时执行一次,且只执行一次:

java

9

1

2

3

4

5

6

7

8

9

class Config {

static String version;

static {

version = "v1.0";

System.out.println("静态代码块:类加载时执行一次");

}

}

执行顺序:静态代码块 → 构造代码块 → 构造方法

十一、实战练习

练习1:设计一个 BankAccount 类

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

class BankAccount {

private String owner;

private double balance;

BankAccount(String owner, double balance) {

this.owner = owner;

this.balance = balance;

}

void deposit(double amount) {

if (amount <= 0) {

System.out.println("存款金额必须大于0");

return;

}

balance += amount;

System.out.println(owner + "存入" + amount + "元,余额:" + balance);

}

void withdraw(double amount) {

if (amount > balance) {

System.out.println("余额不足!");

return;

}

balance -= amount;

System.out.println(owner + "取出" + amount + "元,余额:" + balance);

}

void showBalance() {

System.out.println(owner + "的账户余额:" + balance + "元");

}

}

练习2:统计创建了多少个对象

java

99

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class User {

String name;

static int count = 0; // 静态变量:计数器

User(String name) {

this.name = name;

count++; // 每创建一个对象,计数+1

System.out.println("创建用户:" + name + ",当前总人数:" + count);

}

}

new User("张三"); // 创建用户:张三,当前总人数:1

new User("李四"); // 创建用户:李四,当前总人数:2

new User("王五"); // 创建用户:王五,当前总人数:3

十二、总结速查表

表格

概念 要点
类 vs 对象 类是图纸,对象是实例;一个类可以创建多个对象
构造方法 与类同名、无返回值、new 时自动调用;不写则有默认无参构造
this 指代当前对象;解决变量同名冲突;this() 调用其他构造方法
封装 private 属性 + public getter/setter + 数据校验
成员变量 vs 局部变量 成员变量有默认值、属于对象;局部变量无默认值、属于方法
方法重载 同名不同参(个数/类型/顺序),与返回值无关
static 属于类而非对象;静态方法不能直接访问非静态成员
代码块 静态代码块(类加载时一次)→ 构造代码块(每次new)→ 构造方法

面向对象是 Java 的灵魂,今天搞懂了类和对象,后面学继承和多态就有了根基。你已经站在了 OOP 的大门口,推门进去吧!💪

更多推荐