Java——封装(Encapsulation)

一、封装简介

1、封装是什么

封装(Encapsulation) 是面向对象编程(OOP)中的一个基本概念,它指的是将对象的状态(数据)和行为(方法)绑定在一起,并对外隐藏对象的内部细节。在Java中,封装通过使用访问修饰符(如 privateprotectedpublic)来实现,这些修饰符控制类的成员(变量和方法)的可见性和访问级别。封装在Java中确实涉及将类的部分实现细节(包括数据和方法)隐藏起来,只对外暴露必要的抽象接口。

封装可以被视为一种保护屏障,它通过限制外部代码对类内部数据和方法的直接访问,提供了对类的内部实现的保护。要访问该类的代码和数据,必须通过严格的接口控制。封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

打个比较生动的例子就是当我们使用手机时,我们不需要了解其内部电路、处理器、内存或其他硬件组件的具体工作原理。相反,我们只需要使用手机提供的各种功能和应用程序,如拨打电话、发送短信、浏览网页、拍照等。

2、封装的好处

  • 提高安全性:通过隐藏内部数据,可以防止外部代码直接操作数据,从而减少错误和提高安全性。
  • 简化代码的使用:使用者只需要知道类的公共接口,而不需要了解内部实现细节。
  • 易于修改和维护:类的内部实现可以自由修改,而不影响使用该类的其他代码。

二、封装的详细步骤

1. 将属性进行私有化(private)

java 复制代码
class Person {
	private String name;
	private int age;
}

2. 提供一个公共的 set 方法,用于对属性判断并赋值

java 复制代码
class Person {
	private String name;
	private int age;

	public void setName(String name) {
		if(name != null && name.length() >= 2 && name.length() <= 6) {
			this.name = name;
		} else {
			throw new IllegalArgumentException("名字长度应当在 2-6 个字");
		}
	}

	public void setAge(int age) {
		if(age >= 0 && age <= 200) {
			this.age = age;
		} else {
			throw new IllegalArgumentException("年龄应当在 0-200 之间");
		}
	}
}

3. 提供一个公共的 get 方法,用于获取属性的值

java 复制代码
class Person {
	private String name;
	private int age;

	public void setName(String name) {
		if(name != null && name.length() >= 2 && name.length() <= 6) {
			this.name = name;
		} else {
			throw new IllegalArgumentException("名字长度应当在 2-6 个字");
		}
	}

	public void setAge(int age) {
		if(age >= 0 && age <= 200) {
			this.age = age;
		} else {
			throw new IllegalArgumentException("年龄应当在 0-200 之间");
		}
	}

	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
}

示例

java 复制代码
package com.pack1;

public class Encapsulation {
	public static void main(String[] args) {
		Person person = new Person();
		person.setName("张三");
		person.setAge(18);
		System.out.println("名字:" + person.getName() + "\n年龄:" + person.getAge());
	}
}

class Person {
	private String name;
	private int age;

	public void setName(String name) {
		if(name != null && name.length() >= 2 && name.length() <= 6) {
			this.name = name;
		} else {
			throw new IllegalArgumentException("名字长度应当在 2-6 个字");
		}
	}

	public void setAge(int age) {
		if(age >= 0 && age <= 200) {
			this.age = age;
		} else {
			throw new IllegalArgumentException("年龄应当在 0-200 之间");
		}
	}

	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
}

运行结果:

可以发现这里我们可以使用 setter 对私有属性进行配置,可以使用 getter 对私有属性进行获取。而不是直接对属性进行访问。

三、补充

1、构造器与 setter 相结合

我们可以在构造器中使用 setter 已保留那些对属性设置的验证逻辑,也就是保留那些防护机制。

java 复制代码
package com.pack1;

public class Encapsulation {
	public static void main(String[] args) {
		try {
			Person person = new Person("张三",18); // 合法姓名和年龄
			System.out.println("姓名: " + person.getName() + "\n年龄" + person.getAge());

			// 非法姓名,将引发异常
			Person person2 = new Person("",18);
		} catch (IllegalArgumentException e) {
			System.out.println(e.getMessage());
		}
	}
}

class Person {
	private String name;
	private int age;

	//使用 setter 的构造器
	public Person(String name, int age) {
		setName(name);
		setAge(age);
	}

	public void setName(String name) {
		if(name != null && name.length() >= 2 && name.length() <= 6) {
			this.name = name;
		} else {
			throw new IllegalArgumentException("名字长度应当在 2-6 个字");
		}
	}

	public void setAge(int age) {
		if(age >= 0 && age <= 200) {
			this.age = age;
		} else {
			throw new IllegalArgumentException("年龄应当在 0-200 之间");
		}
	}

	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
}

运行结果:

可以发现这里使用构造器传入错误的参数依旧会抛出异常,可以发现将构造器与 setter 相结合使用可以保留对参数的验证。

相关推荐
flyair_China15 分钟前
【云架构】
开发语言·php
pengyu17 分钟前
【Java设计原则与模式之系统化精讲:壹】 | 编程世界的道与术(实战指导篇)
java·后端·设计模式
日月星辰Ace19 分钟前
JVM 垃圾回收简介
java
Chef_Chen22 分钟前
从0开始学习R语言--Day20-ARIMA与格兰杰因果检验
开发语言·学习·r语言
掉头发的王富贵22 分钟前
Arthas神器入门:动态调试Java应用,轻松搞定生产环境Bug!
java·后端·debug
zh_xuan22 分钟前
c++ std::pair
开发语言·c++
Java陈序员27 分钟前
再见 Navicat!一款开源的 Web 数据库管理工具!
java·react.js·docker
知其然亦知其所以然44 分钟前
RAG 结果太水?用 RRF + Reranker 重排,效果翻倍提升!
java·后端·llm
CodeWithMe44 分钟前
【C/C++】EBO空基类优化介绍
开发语言·c++
SimonKing1 小时前
吊打面试官系列:Spring为什么不推荐使用字段依赖注入?
java·后端·架构