面向对象基础:类、对象与封装
面向对象基础:类、对象与封装
面向对象编程(OOP,Object-Oriented Programming)是 Java 的核心编程范式。Java 的一切皆为对象——从字符串到数组,从线程到网络连接,全部以对象的形式存在。理解类与对象的概念,是掌握 Java 的必经之路。本文将深入讲解类的定义、对象的创建、构造器以及封装这一 OOP 基础特性。
类与对象的概念
**类(Class)**是对一类事物的抽象描述,是一个模板或蓝图;**对象(Object)**是类的具体实例,是真实存在的实体。
类:汽车设计图纸
对象:一辆具体的特斯拉 Model 3在 Java 中,先有类,才能创建对象:
// 定义一个 "学生" 类
public class Student {
// ============ 成员变量(属性)===========
String name; // 姓名
int age; // 年龄
String studentId; // 学号
// ============ 构造器(Constructor)===========
// 无参构造器
public Student() {
}
// 有参构造器
public Student(String name, int age, String studentId) {
this.name = name;
this.age = age;
this.studentId = studentId;
}
// ============ 成员方法(行为)===========
void study() {
System.out.println(name + " 正在学习...");
}
void introduce() {
System.out.println("我叫 " + name + ",今年 " + age + " 岁,学号是 " + studentId);
}
}// 创建对象(实例化)
Student alice = new Student("Alice", 20, "S2024001");
alice.introduce();
// 我叫 Alice,今年 20 岁,学号是 S2024001
alice.study();
// Alice 正在学习...
// 再创建一个独立的对象
Student bob = new Student("Bob", 22, "S2024002");
bob.introduce();
// 我叫 Bob,今年 22 岁,学号是 S2024002关键点:每个对象都是独立的实例,拥有自己的属性值。修改
alice的name不会影响bob。
成员变量与成员方法
成员变量
成员变量(Field)定义在类内部、方法外部,描述对象的状态:
public class Rectangle {
// 成员变量(实例变量),每个对象独立一份
double width;
double height;
// 静态变量(类变量),所有对象共享一份
static int instanceCount = 0;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
instanceCount++; // 每创建一个实例,计数器加一
}
double area() {
return width * height;
}
double perimeter() {
return 2 * (width + height);
}
}Rectangle r1 = new Rectangle(3.0, 4.0);
Rectangle r2 = new Rectangle(5.0, 6.0);
System.out.println(r1.area()); // 12.0
System.out.println(r2.area()); // 30.0
// 静态变量通过类名访问
System.out.println(Rectangle.instanceCount); // 2成员方法
成员方法定义在类内部,描述对象的行为:
public class Counter {
private int count = 0; // 私有变量,外部无法直接访问
// 递增
public void increment() {
count++;
}
// 递减
public void decrement() {
count--;
}
// 获取当前值
public int getCount() {
return count;
}
// 重置
public void reset() {
count = 0;
}
}构造器
构造器是创建对象时自动调用的特殊方法,用于初始化对象的状态。
无参构造器
如果类中没有显式定义任何构造器,Java 编译器会自动生成一个无参构造器(默认构造器):
public class Dog {
String name;
// 如果不写构造器,Java 会自动生成:
// public Dog() {}
}
// 使用无参构造器创建对象
Dog dog = new Dog();
dog.name = "旺财";有参构造器(推荐)
public class Dog {
String name;
String breed;
int age;
// 有参构造器:创建时直接初始化
public Dog(String name, String breed, int age) {
this.name = name;
this.breed = breed;
this.age = age;
}
void bark() {
System.out.println(name + " 汪汪叫!");
}
void info() {
System.out.println(name + " 是一只 " + age + " 岁的 " + breed + "。");
}
}Dog myDog = new Dog("旺财", "金毛", 3);
myDog.bark(); // 旺财 汪汪叫!
myDog.info(); // 旺财 是一只 3 岁的金毛。构造器重载
同方法一样,构造器也支持重载——定义多个参数列表不同的构造器:
public class User {
String username;
String email;
int age;
// 构造器重载
public User() {
// 默认值
this.username = "匿名";
this.email = "unknown@example.com";
this.age = 0;
}
public User(String username, String email) {
this.username = username;
this.email = email;
this.age = 18; // 默认年龄
}
public User(String username, String email, int age) {
this.username = username;
this.email = email;
this.age = age;
}
}this 关键字
this 指向当前对象,用于区分成员变量和局部变量(同名时必须用 this):
public class Point {
int x;
int y;
public Point(int x, int y) {
// this.x 表示当前对象的成员变量 x
// x 表示参数中的局部变量 x
this.x = x;
this.y = y;
}
// this 还可以调用同类中的其他构造器(必须在构造器第一行)
public Point() {
this(0, 0); // 调用另一个构造器 Point(int, int)
}
void move(int dx, int dy) {
this.x += dx;
this.y += dy;
}
}访问修饰符与封装
**封装(Encapsulation)**是 OOP 的三大特性之一(另外两个是继承和多态),指的是将数据和操作数据的代码组织在一起,对外隐藏实现细节,仅暴露必要的接口。
访问修饰符
Java 提供四个层级的访问控制:
| 修饰符 | 同一类内 | 同一包内 | 子类(不同包) | 任意位置 |
|---|---|---|---|---|
private | ✅ | ❌ | ❌ | ❌ |
default(无修饰符) | ✅ | ✅ | ❌ | ❌ |
protected | ✅ | ✅ | ✅ | ❌ |
public | ✅ | ✅ | ✅ | ✅ |
public class Person {
public String name; // 公开:任何地方都能访问
protected int age; // 受保护:子类和同包可访问
private String idCard; // 私有:仅本类内部可访问
String address; // 默认(包私有):同包内可访问
}实现封装:getter / setter
将成员变量设为 private,通过 public 方法访问,这就是最常见的封装模式:
public class BankAccount {
// 私有化属性,外部无法直接访问
private String accountNumber;
private double balance;
// 构造器
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// Getter(读取)
public String getAccountNumber() {
return accountNumber;
}
public double getBalance() {
return balance;
}
// Setter(写入),可加入业务校验逻辑
public void deposit(double amount) {
if (amount <= 0) {
System.out.println("存款金额必须为正数");
return;
}
this.balance += amount;
System.out.println("存款成功,当前余额:" + this.balance);
}
public void withdraw(double amount) {
if (amount <= 0) {
System.out.println("取款金额必须为正数");
return;
}
if (amount > this.balance) {
System.out.println("余额不足!");
return;
}
this.balance -= amount;
System.out.println("取款成功,当前余额:" + this.balance);
}
}BankAccount account = new BankAccount("6222021234567890", 1000.0);
// 无法直接访问私有属性
// account.balance = 1000000; // 编译错误!
account.deposit(500); // 存款成功,当前余额:1500.0
account.withdraw(300); // 取款成功,当前余额:1200.0
System.out.println("账户:" + account.getAccountNumber());
System.out.println("余额:" + account.getBalance());封装的好处:1)保护数据不被非法值破坏;2)隐藏内部实现,外部只依赖接口;3)便于后期维护和修改内部逻辑而不影响调用方。
Lombok 简化 getter/setter(可选)
在实际项目中,手写 getter/setter 繁琐,通常使用 Lombok 注解自动生成:
import lombok.Getter;
import lombok.Setter;
public class Product {
@Getter @Setter
private String name;
@Getter @Setter
private double price;
@Getter @Setter
private int stock;
}
// 编译后 Lombok 会自动生成 getName()、setName()、getPrice() 等方法完整示例:自定义数组容器
让我们用一个完整的示例串联所有知识点:
public class IntList {
private int[] data; // 内部数组
private int size; // 当前元素个数
// 构造器:初始容量为 10
public IntList() {
this.data = new int[10];
this.size = 0;
}
// 添加元素
public void add(int value) {
if (size >= data.length) {
resize(); // 容量翻倍
}
data[size++] = value;
}
// 获取指定位置元素
public int get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界: " + index);
}
return data[index];
}
// 获取当前元素个数
public int size() {
return size;
}
// 扩容方法(内部使用)
private void resize() {
int[] newData = new int[data.length * 2];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
// 打印所有元素
public void printAll() {
System.out.print("[ ");
for (int i = 0; i < size; i++) {
System.out.print(data[i]);
if (i < size - 1) System.out.print(", ");
}
System.out.println(" ]");
}
}IntList list = new IntList();
list.add(10);
list.add(20);
list.add(30);
list.printAll(); // [ 10, 20, 30 ]
System.out.println("大小:" + list.size()); // 大小:3
System.out.println("第1个元素:" + list.get(0)); // 第1个元素:10小结
- 类是模板,对象是类的实例;使用
new关键字创建对象 - 成员变量描述对象状态,成员方法描述对象行为;
static变量为类变量,所有实例共享 - 构造器用于初始化对象,支持重载;
this关键字解决成员变量与参数同名冲突 - 封装通过
private隐藏数据,public方法(getter/setter)提供受控访问 private最常用——除非明确需要外部访问,不要将成员变量设为public
掌握类与对象后,下一节我们将学习面向对象的核心特性——继承、多态与接口,这是 Java 实现代码复用和多态行为的关键机制。
评论
Written by
AI-Writer
Related Articles
集合框架与 Stream API
系统讲解 Java 三大集合体系(List/Set/Map)、核心实现类、Stream API 筛选映射归约操作、Lambda 表达式与方法引用
Read MoreJDBC 与数据库交互
详解 JDBC 编程五步曲:加载驱动、建立连接、执行 SQL、处理结果集,以及 PreparedStatement 防注入、事务控制和连接池原理
Read More