本文通过贴近生活的比喻和清晰的代码图示,深入浅出地讲解面向对象编程(OOP)中的关键概念——类、对象与封装,帮助你掌握其核心逻辑。
不同的编程范式体现了不同的问题解决思路。理解这两种思维方式是掌握面向对象的第一步。
面向过程关注“怎么做”,强调步骤和流程,程序员亲自处理每一个细节。
举例:公司打扫卫生
思考路径:我自己擦玻璃 → 扫地 → 拖地 → 倒垃圾
特点:事必躬亲,效率低,维护难。
面向对象关注“让谁做”,将任务分配给合适的对象,只需发出指令。
举例:公司打扫卫生
思考路径:安排小明负责擦玻璃,小丽扫地,小郭拖地,小强倒垃圾
特点:分工明确,调用简单,扩展性强。
上网查参数→电脑城询价→回家分析→现场监督装机→安装系统→抱回家
找个懂电脑的朋友→告诉他需求→等结果
核心总结:
面向过程适用于逻辑简单的场景,属于“执行者思维”;
面向对象更适合复杂系统,是一种“指挥者思维”。
在面向对象中,一个对象由两部分构成:属性(描述状态的数据)和方法(可执行的行为)。
类是对一类事物的抽象定义,而对象是这个类的具体表现。可以用“模具”与“产品”的关系来理解:
类 = 模具,对象 = 用模具生产出的实际物品。
在Java中,类使用 class 关键字定义,包含成员变量(属性)和成员方法(行为)。
public class 类名 {
// 成员属性(变量)
数据类型 变量名1;
数据类型 变量名2;
// 成员方法(功能)
修饰符 返回值类型 方法名(参数) {
执行语句;
}
}
我们可以通过定义 Car 类来描述一辆车的基本特征和功能。
public class Car {
String color; // 颜色属性
int number; // 轮胎数量
// 运行功能
void run() {
System.out.println(color + "的车,有" + number + "个轮胎,正在奔跑!");
}
}
使用 new 关键字根据类创建对象,并通过引用变量访问其属性和方法。
public class CarDemo {
public static void main(String[] args) {
// 1. 创建对象(new关键字)
Car c = new Car(); // c是引用变量,指向堆内存中的Car对象
// 2. 访问属性赋值
c.color = "红色";
c.number = 4;
// 3. 调用方法
c.run(); // 输出:红色:4
}
}
了解对象在内存中的存储方式有助于深入理解Java运行机制。
对象创建过程如下:
Person p = new Person();
p.setAge(30);
p
当调用对象的方法时:
this 关键字代表当前正在调用方法的那个对象。p.setAge(30)
this.age = age
关键理解:
this 指的是调用当前方法的对象。哪个对象调用了方法,this 就指向哪个对象。
this
| 对比维度 | 成员变量 | 局部变量 |
|---|---|---|
| 定义位置 | 类中,方法外部 | 方法内部或代码块内 |
| 内存位置 | 堆内存(随对象存在) | 栈内存(随方法调用) |
| 生命周期 | 对象创建时诞生,销毁时消失 | 方法调用时存在,弹栈后释放 |
| 初始化 | 有默认值(0, null, false等) | 必须手动初始化才能使用 |
| 作用域 | 整个类范围内可见 | 仅限当前方法内部 |
{}
Java中参数传递分为两种情况,理解它们对避免常见错误至关重要。
传递的是变量值的副本,形参的修改不影响实参。
public static void main(String[] args) {
int x = 4;
show(x); // 传递的是值"4"的副本
System.out.println("x="+x); // 输出:x=4
}
public static void show(int x) {
x = 5; // 只修改了副本,不影响main中的x
}
图解说明:就像复印一份文件,修改复印件不会影响原件内容。
传递的是对象地址的副本,多个引用指向同一对象,因此可以共同修改对象数据。
public static void main(String[] args) {
Demo d = new Demo();
d.x = 5;
show(d); // 传递的是地址值的副本
System.out.println("x="+d.x); // 输出:x=6
}
public static void show(Demo d) {
d.x = 6; // 通过地址修改了同一个对象
}
图解说明:如同给了两张相同的家庭住址纸条,都能找到同一个家,任何改动都会反映在实际房屋上。
封装是面向对象三大特性之一(封装、继承、多态),其核心理念是:
隐藏内部实现细节,仅暴露安全的操作接口。
private
问题场景:若年龄属性公开,可能被非法赋值为负数。
class Person {
int age; // 可以被任意赋值
}
Person p = new Person();
p.age = -20; // 不合理,但编译通过!
解决方案:将属性设为 private,并提供公共的 get/set 方法进行受控访问。
private
class Person {
private int age; // 只能在类内部访问
// 对外提供公共的set/get方法
public void setAge(int a) {
if (a < 0 || a > 130) {
System.out.println("年龄不合法!");
return;
}
age = a;
}
public int getAge() {
return age;
}
}
封装的优势:
编码规范建议:
所有类的属性应声明为 private,并配套提供 public 的 get 和 set 方法。
setXxx/getXxx
当成员变量与局部变量同名时,需要借助 this 来区分。
this 表示当前调用方法的对象本身,用于访问本对象的成员。
this
class Person {
private int age;
public void setAge(int age) { // 局部变量age和成员变量age同名
this.age = age; // this.age代表成员变量,age代表局部变量
}
}
利用 this 获取当前对象的年龄,与其他对象比较。
public boolean equalsAge(Person p) {
// this.age:调用者的年龄
// p.age:传入对象的年龄
return this.age == p.age;
}
// 使用
Person p1 = new Person();
p1.setAge(18);
Person p2 = new Person();
p2.setAge(20);
System.out.println(p1.equalsAge(p2)); // false
结合所学知识重构传统数组实现的点名程序。
ArrayList<Student>
Student
Student.java
public class Student {
private String name;
private int age;
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; }
}
CallName.java
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Random;
public class CallName {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
addStudent(list); // 1. 存储信息
printStudent(list); // 2. 打印信息
randomStudent(list); // 3. 随机点名
}
// 存储学生信息
public static void addStudent(ArrayList<Student> list) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
Student s = new Student();
System.out.print("请输入第" + (i+1) + "位学生姓名:");
s.setName(sc.next());
System.out.print("请输入第" + (i+1) + "位学生年龄:");
s.setAge(sc.nextInt());
list.add(s);
}
}
// 打印所有学生信息
public static void printStudent(ArrayList<Student> list) {
System.out.println("\n全班同学信息:");
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println("姓名:" + s.getName() + ",年龄:" + s.getAge());
}
}
// 随机点名
public static void randomStudent(ArrayList<Student> list) {
int index = new Random().nextInt(list.size());
Student s = list.get(index);
System.out.println("\n???? 被点名的同学:" + s.getName() + ",年龄:" + s.getAge());
}
}
运行效果预览:
请输入第1位学生姓名:张三
请输入第1位学生年龄:20
请输入第2位学生姓名:李四
请输入第2位学生年龄:21
请输入第3位学生姓名:王五
请输入第3位学生年龄:19
全班同学信息:
姓名:张三,年龄:20
姓名:李四,年龄:21
姓名:王五,年龄:19
???? 被点名的同学:李四,年龄:21
回顾本篇重点内容,强化记忆。
new 关键字创建。| 关键字 | 作用 | 记忆口诀 |
|---|---|---|
| private | 限制成员访问,实现数据隐藏 | "private像保险柜,数据藏里面" |
| this | 指代当前调用方法的对象 | "this指自己,谁调用就指谁" |
| new | 创建新的对象实例,在堆中分配空间 | "new出新对象,内存开空间" |
new
private
this
new面向对象编程的核心理念在于:
将复杂的问题简化,把简单的问题通过对象的方式进行抽象和处理。
在实际编码过程中,需要遵循一定的规范以保证代码的可读性和维护性:
上网查参数→电脑城询价→回家分析→现场监督装机→安装系统→抱回家
今天所学习的类、对象以及封装机制,是面向对象编程(OOP)的重要基础。建议通过大量的编程练习来深入理解和熟练掌握这些核心概念。
扫码加好友,拉您进群



收藏
