Appearance
面向对象基础
前置知识
在阅读本章前,你需要了解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();
}
}这段代码做了什么:
- 定义了
Car类,里面有两个属性color和brand,还有一个展示汽车信息的方法。 - 在
main方法里,我们“造”了一个Car对象,叫myCar。 - 为对象赋了颜色和品牌,接着调用它的方法显示信息。
封装:保护数据的“小房间”
简单定义
直接让对象的属性“裸奔”很危险,你可能想给别人看的只能是方法,不允许直接修改重要属性。封装就是用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();
}
}这段代码做了什么:
- 使用
private隐藏name和age属性。 - 通过构造方法初始化对象。
- 公开
getName和setAge方法控制属性访问,其中setAge带了简单的有效性检查。 - 在
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();
}
}这段代码做了什么:
- 定义了含有属性和两个构造方法的
Book类,支持不同参数初始化。 - 通过
this(...)实现构造方法间的调用,避免重复代码。 - 体现了
this关键字在属性赋值和构造调用中的应用。 - 测试了不同构造方式创建的对象并打印信息。
对象创建过程概览
简单理解:当执行new ClassName()时:
- JVM分配内存给新对象。
- 初始化默认值(数值为0,布尔为false,对象为null)。
- 调用构造方法,执行代码给属性赋初始值。
- 返回对象引用。
这一步很关键,也是你理解后续OOP高级特性(如继承、多态)的基础。
⚠️ 常见陷阱
- 构造方法和普通方法不可重载返回类型,只能通过参数列表区分。
- 使用
this引用对象属性时,确保没有写成赋值反了(比如name = this.name;是错的)。 - 直接暴露
public属性容易造成意外修改,养成封装的习惯,提升代码健壮性。 - 构造方法中的代码执行顺序非常重要,初始化顺序和逻辑错误可能导致bug难排。
实战建议
在实际项目中,我发现:
- 先设计好类的属性和责任,切忌一开始追求复杂功能而写一大堆混乱代码。
- 构造方法中应该尽量保持简单,复杂逻辑放到其他初始化方法或用工厂模式处理。
- 面向对象的核心是建模,花时间思考哪个类应该负责哪些行为。
- 封装不仅保护了数据,也让类的使用者更容易理解和使用你的代码。
小结
- 类是抽象模板,对象是具体实例。
- 封装用
private隐藏数据,通过getter、setter控制访问。 - 构造方法用于初始化对象,
this关键字指当前对象并解决变量名冲突。 - 创建对象时,JVM会分配内存、执行构造方法,确保对象准备好被使用。
这些基础知识是你面向对象编程的地基,牢固它,才能搭建出更复杂灵活的软件结构。
延伸思考
- 当一个类中属性非常多时,构造方法如何设计才能不让代码臃肿?
- 你能想到除了构造方法初始化对象外,还有哪些创建和初始化对象的方式?
- 你有没有遇到过变量名和参数名冲突没有用
this导致的奇怪bug?可以试着模拟一下。
如果你准备好了,我们下一章会带你深入理解继承和多态,这可是面向对象真正的魔法——让代码变得灵活又强大。我们一起走下去!
