一篇文章让你学会Java之类的封装

365bet在线客服 📅 2025-10-04 13:46:30 ✍️ admin 👁️ 7887 ❤️ 535
一篇文章让你学会Java之类的封装

类的封装

一、 什么是封装?二、 封装的三个步骤三、 封装的完整代码示例类定义:封装的实现使用封装的类:测试代码

四、 `this`关键字的使用代码回顾1. `this` 的作用详解1.1 `this` 是什么?1.2 `this` 的用法

2. 为什么要用 `this`?2.1 没有 `this` 时的问题2.2 使用 `this` 的解决方法

3. 深入理解 `this` 的作用3.1 `this` 的隐含含义运行结果:

3.2 `this` 访问类的属性和方法3.3 `this` 调用构造方法

4. `this` 总结

五、 封装的优势六、 封装的细节与扩展1. 只读和只写属性2. 属性的访问控制级别3. 数据校验逻辑4. 自动生成`getter`和`setter`5. 使用封装设计复杂类

七、 封装与设计原则

一、 什么是封装?

封装(Encapsulation)是面向对象编程(OOP)的核心特性之一。它强调将数据和行为整合到类中,并通过限制外部对数据的直接访问,保护数据的安全性。

简单来说:

封装是对类的内部实现细节进行隐藏,对外部暴露统一的访问接口。外部程序只能通过类提供的公开方法(如getter和setter)与类的内部数据交互,无法直接修改或访问类的内部数据。

封装的核心思想是:隐藏细节,控制访问。

二、 封装的三个步骤

要实现封装,需要遵循以下三个步骤:

将类的属性声明为私有(private)。

私有化后,属性只能在类的内部访问,外部类无法直接修改或读取这些属性。 为私有属性提供getter和setter方法。

getter方法用于获取属性值。setter方法用于设置属性值,并可以在方法中添加逻辑,进行校验和控制。 限制访问级别,根据需要对外提供访问接口。

通过方法来控制数据的读写权限,比如可以设置属性为只读、只写或可读可写。

三、 封装的完整代码示例

以下是一个实现封装的例子:

类定义:封装的实现

public class Student {

// 私有属性

private String name;

private int age;

// Getter方法:获取name属性

public String getName() {

return name;

}

// Setter方法:设置name属性

public void setName(String name) {

this.name = name;

}

// Getter方法:获取age属性

public int getAge() {

return age;

}

// Setter方法:设置age属性(带校验逻辑)

public void setAge(int age) {

if (age > 0 && age < 120) {

this.age = age;

} else {

System.out.println("年龄不合法,请输入1-120之间的值!");

}

}

}

使用封装的类:测试代码

public class Main {

public static void main(String[] args) {

Student student = new Student();

// 设置属性值

student.setName("Alice");

student.setAge(25);

// 获取属性值

System.out.println("姓名:" + student.getName()); // 输出:姓名:Alice

System.out.println("年龄:" + student.getAge()); // 输出:年龄:25

// 测试非法数据

student.setAge(-5); // 输出:年龄不合法,请输入1-120之间的值!

}

}

四、 this关键字的使用

代码回顾

这是一个实现封装的简单类,用于管理Employee的姓名和工资:

public class Employee {

// 1. 私有属性

private String name; // 姓名

private double salary; // 工资

// 2. 提供getter方法:获取name属性

public String getName() {

return name;

}

// 3. 提供setter方法:设置name属性

public void setName(String name) {

// this.name 是指当前类的属性,name 是方法参数

this.name = name;

}

// getter方法:获取salary属性

public double getSalary() {

return salary;

}

// setter方法:设置salary属性

public void setSalary(double salary) {

// 数据校验:工资不能为负数

if (salary > 0) {

this.salary = salary;

} else {

System.out.println("工资必须大于0!");

}

}

}

1. this 的作用详解

在封装代码中,this 是一个非常重要的关键字,主要用于解决类的属性和方法参数(或局部变量)同名的问题。

1.1 this 是什么?

this 是一个指向当前对象的引用。具体来说,当类的某个方法被调用时,Java 会将调用该方法的对象的引用(即当前对象)作为隐含参数传递给方法。this 的作用是指代调用方法的当前对象。

1.2 this 的用法

访问当前对象的属性:

当方法的参数名或局部变量名与类的属性名相同时,this 用于区分类的属性和方法的局部变量。格式:this.属性名 调用当前对象的方法:

使用this可以调用当前对象的其他方法。格式:this.方法名() 调用当前类的构造方法:

使用this()可以在一个构造方法中调用另一个构造方法。

2. 为什么要用 this?

2.1 没有 this 时的问题

在setName方法中,参数名是name,而类的属性名也是name。如果不使用this,会出现以下问题:

public void setName(String name) {

name = name; // 这实际上是在给参数自己赋值,类的属性name没有被修改

}

在上面的代码中,name 是方法的参数,而非类的属性。由于局部变量(参数name)优先级高,它会覆盖同名的类属性。因此,赋值语句 name = name; 只是在把方法参数name赋值给它自己,而不是给类的属性赋值。

2.2 使用 this 的解决方法

为了明确表示赋值的目标是类的属性,而不是方法的参数,我们使用this:

public void setName(String name) {

this.name = name; // this.name 是类的属性,name 是方法的参数

}

this.name: 表示当前对象的属性name。name: 表示方法的参数name。

3. 深入理解 this 的作用

3.1 this 的隐含含义

假设我们创建了两个Employee对象,每个对象都有自己的name和salary。this 指代调用方法的具体对象。

代码如下:

public class Main {

public static void main(String[] args) {

Employee emp1 = new Employee();

Employee emp2 = new Employee();

emp1.setName("Alice");

emp1.setSalary(5000);

emp2.setName("Bob");

emp2.setSalary(7000);

System.out.println(emp1.getName() + " 的工资是 " + emp1.getSalary());

System.out.println(emp2.getName() + " 的工资是 " + emp2.getSalary());

}

}

运行结果:

Alice 的工资是 5000.0

Bob 的工资是 7000.0

在这里:

emp1.setName("Alice") 中,this 代表 emp1。emp2.setName("Bob") 中,this 代表 emp2。

每个对象都有独立的属性,this 可以正确地将方法调用与具体的对象绑定。

3.2 this 访问类的属性和方法

this 可以在类中访问属性和方法:

示例:在setter方法中调用getter方法

public void setName(String name) {

if (name != null && !name.trim().isEmpty()) {

this.name = name;

} else {

System.out.println("姓名无效,设置为默认值!");

this.name = "默认姓名";

}

// 调用getter方法,打印当前设置的值

System.out.println("当前姓名:" + this.getName());

}

测试代码:

Employee emp = new Employee();

emp.setName(""); // 输出:姓名无效,设置为默认值! 当前姓名:默认姓名

在这里,this.getName() 调用了当前对象的 getName 方法。

3.3 this 调用构造方法

this 还可以用来调用类的其他构造方法,以简化代码。

示例:调用另一个构造方法

public class Employee {

private String name;

private double salary;

// 无参构造方法

public Employee() {

this("默认姓名", 0.0); // 调用有参构造方法

}

// 有参构造方法

public Employee(String name, double salary) {

this.name = name;

this.salary = salary;

}

public String getName() {

return name;

}

public double getSalary() {

return salary;

}

}

测试代码:

public class Main {

public static void main(String[] args) {

Employee emp = new Employee(); // 无参构造

System.out.println(emp.getName()); // 输出:默认姓名

System.out.println(emp.getSalary()); // 输出:0.0

}

}

4. this 总结

this 是当前对象的引用。常见用法:

访问当前对象的属性(this.属性名)。调用当前对象的方法(this.方法名())。在构造方法中调用另一个构造方法(this(参数...))。

在封装中,this 是关键字,它帮助我们正确地处理方法参数和类属性之间的同名问题。

五、 封装的优势

提高代码的安全性

将数据隐藏起来,防止外部代码随意修改对象的内部状态。通过getter和setter方法,可以对数据进行校验或限制,避免出现非法值。 提高代码的可维护性

隐藏实现细节,类的内部实现可以随时修改,而不会影响外部调用代码。如果属性或逻辑需要改变,只需修改类内部的代码,外部使用类的接口无需修改。 增强代码的灵活性

可以根据需要提供只读或只写属性。通过getter和setter方法,可以动态地控制属性值的获取或设置逻辑。 模块化设计

类的属性和行为被封装在一起,形成一个独立的模块,便于代码管理和重用。

六、 封装的细节与扩展

1. 只读和只写属性

只读属性: 只提供getter方法,不提供setter方法。只写属性: 只提供setter方法,不提供getter方法。

示例代码:

public class Account {

private String accountNumber; // 只读属性

private double balance; // 只写属性

// Getter方法(只读属性)

public String getAccountNumber() {

return accountNumber;

}

// Setter方法(只写属性)

public void setBalance(double balance) {

if (balance >= 0) {

this.balance = balance;

} else {

System.out.println("余额不能为负数!");

}

}

}

2. 属性的访问控制级别

Java提供了4种访问控制修饰符,用于限制类、属性和方法的访问权限:

修饰符类内部同包子类跨包public√√√√protected√√√×默认(无修饰符)√√××private√×××

建议:

属性一般使用private,完全隐藏;方法根据需要设置为public、protected或默认。

3. 数据校验逻辑

封装的一个重要作用是保护数据的合法性。setter方法通常会包含数据校验逻辑。

例如:

限制年龄范围:

public void setAge(int age) {

if (age > 0 && age <= 150) {

this.age = age;

} else {

System.out.println("年龄必须在1到150之间!");

}

}

限制密码长度:

public void setPassword(String password) {

if (password.length() >= 6 && password.length() <= 20) {

this.password = password;

} else {

System.out.println("密码长度必须在6到20个字符之间!");

}

}

4. 自动生成getter和setter

在实际开发中,手写getter和setter方法可能较繁琐,IDE(如IntelliJ IDEA或Eclipse)提供了自动生成工具:

在IDE中右键点击代码空白处。选择 Generate 或 Source → Generate Getters and Setters。选择需要生成的方法,点击完成即可。

5. 使用封装设计复杂类

以下是一个复杂的封装类示例:

public class BankAccount {

private String accountNumber; // 账号

private double balance; // 余额

private String owner; // 户主

public BankAccount(String accountNumber, String owner) {

this.accountNumber = accountNumber;

this.owner = owner;

this.balance = 0.0; // 初始化余额为0

}

// 获取账号(只读)

public String getAccountNumber() {

return accountNumber;

}

// 获取余额

public double getBalance() {

return balance;

}

// 存款方法

public void deposit(double amount) {

if (amount > 0) {

balance += amount;

System.out.println("存款成功!当前余额:" + balance);

} else {

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

}

}

// 取款方法

public void withdraw(double amount) {

if (amount > 0 && amount <= balance) {

balance -= amount;

System.out.println("取款成功!当前余额:" + balance);

} else {

System.out.println("余额不足或取款金额不合法!");

}

}

}

测试代码:

public class Main {

public static void main(String[] args) {

BankAccount account = new BankAccount("123456", "Alice");

account.deposit(1000); // 存款

account.withdraw(500); // 取款

account.withdraw(700); // 尝试超额取款

}

}

输出:

存款成功!当前余额:1000.0

取款成功!当前余额:500.0

余额不足或取款金额不合法!

七、 封装与设计原则

封装的实现遵循了面向对象设计原则中的以下两点:

单一职责原则(SRP):

每个类封装自己的职责,互不干扰。例如BankAccount类只负责账户相关的操作。 开闭原则(OCP):

封装让类对扩展开放,对修改关闭。例如可以添加新的方法或逻辑,而不会影响外部使用的接口。

相关创意

CBA战队推出世界杯主题公益宣传海报
为何张姓是中国三大姓氏之一?虽非皇族后裔,江湖地位却举足轻重
龙之谷怎么浇水?
没有找到站点
dnf宝珠用不了是怎么回事
学生篇 – iSmart
流量密碼!日本妹「野外排泄」大方露 吸出千萬點閱
清眸的解释
“修罗场”是什么意思?