封装(数据的隐藏)
私有属性实现方式:get/set
封装(Encapsulation)是面向对象编程中的一个核心概念,它指的是将对象的内部状态(即数据)和行为(即方法)隐藏起来,只暴露给外部一些必要的接口,以保护对象的完整性和安全性。
通俗理解:
想象一个遥控器:
- 按钮:这是你能看到和操作的部分,通过按下按钮,你可以让电视机执行某些操作,比如换频道、调音量。这些按钮就是遥控器对外暴露的“接口”。
- 内部电路:这是遥控器的内部结构,它决定了按下按钮时,电视机会发生什么。这些细节被“封装”在遥控器内部,你不用知道内部电路是怎么工作的,只需要知道哪个按钮对应哪个操作。
在 Java 中,封装就是这样一种机制:
- 字段(Field):表示对象的属性,通常用
private
关键字修饰,隐藏起来,防止外部直接访问。 - 方法(Method):表示对象的行为,可以用
public
关键字修饰,作为接口提供给外部使用。
为什么封装很重要?
-
数据保护:通过隐藏对象的内部状态(使用
private
关键字),你可以防止外部代码对数据进行不合适的修改。只有通过指定的公共方法,外部才可以间接修改或访问数据。 -
简化接口:封装可以让类对外提供一个简洁、统一的接口。外部只需要知道如何使用接口,而不需要了解内部的复杂实现。
-
提高可维护性:因为内部实现是隐藏的,你可以在不影响外部代码的情况下修改或优化内部实现,这样代码的可维护性和灵活性更高。
举个例子:
public class Person {
// 私有字段
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公共方法(接口)用于访问或修改私有字段
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) {
this.age = age;
}
}
}
在这个例子中,name
和 age
是私有字段(private
),它们被封装起来,不允许外部直接访问。通过提供公共方法(getName
、setName
、getAge
、setAge
),外部可以在受控的情况下访问和修改这些字段。
在 IntelliJ IDEA 中,快速生成 getter
和 setter
方法
方法一:使用快捷键生成 getter
和 setter
-
定位到类中字段的位置:在代码中,定位到需要生成
getter
和setter
方法的类中。 -
使用快捷键:
- Windows/Linux:按
Alt + Insert
。 - macOS:按
Command + N
或Control + Enter
。
- 选择生成类型:
- 在弹出的菜单中,选择
Getter and Setter
。 - IDEA 会显示一个对话框,列出所有可生成
getter
和setter
方法的字段。
- 选择字段:
- 你可以勾选需要生成
getter
和setter
方法的字段。 - 可以选择仅生成
getter
,或仅生成setter
,或者同时生成二者。
- 点击
OK
:
- 生成的
getter
和setter
方法将自动插入到类中。
方法二:使用“Code”菜单生成 getter
和 setter
-
在类中右键单击:在类的代码区域内,右键单击。
-
选择
Generate...
:在上下文菜单中,选择Generate...
。 -
选择
Getter and Setter
:与快捷键方式相同,选择你想要生成getter
和setter
的字段,然后点击OK
。
方法三:通过 Alt + Enter 快速修复生成
- 声明字段后立即生成:
- 当你声明一个字段后,IDEA 通常会提示你可以生成
getter
和setter
。 - 将光标放在字段名称上,按
Alt + Enter
(Windows/Linux)或Option + Enter
(macOS),选择Generate Getter and Setter
。
这几种方法都可以让你在 IDEA 中快速生成 getter
和 setter
方法,显著提高开发效率。
封装经典案例
Java 中有许多经典的封装案例,它们展示了如何利用封装来提高代码的安全性、可维护性和可扩展性。以下是一些典型的封装案例:
1. JavaBeans 模型
JavaBeans 是 Java 中一种广泛使用的封装模式。JavaBean 是一个可复用的组件,它通常有以下特征:
- 所有属性都是
private
的。 - 每个属性都有对应的
getter
和setter
方法。 - 它有一个无参构造函数。
- 它可以通过实现
Serializable
接口来实现对象的序列化。
示例:
public class Employee {
private String name;
private int age;
private double salary;
// 无参构造函数
public Employee() {}
// 带参构造函数
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) { // 简单的验证逻辑
this.age = age;
}
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
if (salary > 0) { // 简单的验证逻辑
this.salary = salary;
}
}
}
2. 银行账户类
在金融应用中,封装用于保护敏感信息,如账户余额和交易历史。通过封装,可以控制对这些敏感数据的访问,并确保数据的安全性。
示例:
public class BankAccount {
private String accountNumber;
private double balance;
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
if (initialBalance > 0) {
this.balance = initialBalance;
}
}
public String getAccountNumber() {
return accountNumber;
}
public double getBalance() {
return balance;
}
// 存款方法,控制对余额的修改
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
// 取款方法,控制对余额的修改
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
}
3. 不可变类(Immutable Class)
不可变类是一个经典的封装案例,主要用于创建一旦创建就不能改变状态的对象。这种类通常用于确保线程安全性或数据的不可变性。
典型案例:String
类
String
类是 Java 中最常见的不可变类。每次对字符串进行修改时,都会创建一个新的字符串对象,而不是在原有对象上进行修改。
自定义不可变类的示例:
public final class ImmutablePoint {
private final int x;
private final int y;
public ImmutablePoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// 没有 setter 方法,保证了不可变性
}
4. 集合类中的封装
Java 的集合框架中,如 ArrayList
、HashMap
等,都使用了封装来隐藏数据的存储细节,并通过公共接口(如 add
、get
、remove
等方法)来操作数据。
示例:ArrayList
类
ArrayList
内部使用数组存储元素,但这些细节对外部是不可见的。外部通过 add
、get
、remove
等方法来操作列表,而不知道具体的实现细节。
public class MyArrayList {
private Object[] elements;
private int size = 0;
public MyArrayList(int initialCapacity) {
elements = new Object[initialCapacity];
}
public void add(Object element) {
// 省略扩容逻辑
elements[size++] = element;
}
public Object get(int index) {
if (index >= 0 && index < size) {
return elements[index];
} else {
throw new IndexOutOfBoundsException("Index: " + index);
}
}
public int size() {
return size;
}
}
5. 日志记录类
在企业应用中,封装常用于日志记录系统中,确保日志记录的细节对外部不可见,只提供简单易用的接口。
示例:
public class Logger {
private static Logger instance;
private PrintWriter writer;
private Logger() {
try {
writer = new PrintWriter(new FileWriter("app.log", true));
} catch (IOException e) {
e.printStackTrace();
}
}
public static synchronized Logger getInstance() {
if (instance == null) {
instance = new Logger();
}
return instance;
}
public void log(String message) {
writer.println(message);
writer.flush();
}
}
总结
这些经典的封装案例展示了如何通过封装来保护数据、简化接口以及提高代码的安全性和可维护性。封装的核心思想是“隐藏内部实现,暴露必要接口”,从而让代码更易于理解、维护和扩展。
标签:封装,name,int,age,基础,private,java,public From: https://blog.csdn.net/m0_55477902/article/details/141165048