深入理解Java封装:三大特征之一,掌握封装提升编程效率
封装,它算是 Java 的三大特征之一。如果能理清楚,对以后的编程会有较大的帮助。

好的,哥,我已经准备好了。三妹听我说完后,迅速地打开了 XMind。显然,一边学习一边总结思维导图这种高效的学习方式,三妹已经牢牢记住了。
封装从字面理解为包装。专业角度而言,它是信息隐藏。即利用抽象把数据以及基于数据的操作封装起来,让它们构成一个不可分割且独立的实体。
数据被置于类的内部得以保护,内部的实现细节会被尽可能地隐藏起来,只留下一些对外的接口,通过这些接口让其与外部发生联系。
其他对象只能借助已获授权的操作去和这个被封装的对象展开交互。这意味着用户不必知晓对象内部的详情(实际上也无法知晓),然而却能够凭借该对象对外所提供的接口来对其进行访问。
使用封装有 4 大好处:
首先我们先来看两个类。
Husband.java
public class Husband {
/*
* 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性
*/
private String name ;
private String sex ;
private int age ;
private Wife wife;
/*
setter() 是该对象对外开发的接口,getter() 也是该对象对外开发的接口。
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}
Wife.java
public class Wife {
private String name;
private int age;
private String sex;
private Husband husband;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setAge(int age) {
this.age = age;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
public Husband getHusband() {
return husband;
}
}
可以看出,在 Husband 类中,wife 属性没有 getter()。并且,在 Wife 类中,age 属性也没有 getter()方法。至于理由,我想三妹你是明白的。
没有哪个女人愿意别人知道她的年龄。
封装会将一个对象的属性设置为私有。同时,它会提供一些可供外界访问其属性的方法。如果不希望某个属性被外界方法访问,那么我们完全没有必要为外界提供访问该属性的方法。
如果一个类没有给外界提供任何可访问的方法,那么这个类就没有意义了。
我们把一个房子当作一个对象,房子里有漂亮的装饰,像沙发、电视剧、空调、茶桌等这些都是该房子的私有属性。然而,如果没有那些墙的遮挡,别人是不是就会把里面的情况看得一清二楚呢?那就没有一点儿隐私啦!
因为有那个墙在遮挡着,所以我们既能拥有自己的隐私,又能随意更改里面的摆设,并且不会影响到外面的人。
但是一个包裹得严严实实的黑盒子,倘若没有门窗,又能有什么存在的意义呢?所以,因为有门窗,别人才能够看到里面的风景。所以说,门窗就如同房子对象留给外界去访问的接口一般。
通过这个我们无法切实体会到封装的益处。当下我们从程序的层面来剖析封装所带来的好处。倘若我们不运用封装,那么那个对象便不会有 setter()与 getter(),如此一来,Husband 类就应当如此编写:
public class Husband {
public String name ;
public String sex ;
public int age ;
public Wife wife;
}
我们应该这样来使用它:
Husband husband = new Husband();
husband.age = 30;
husband.name = "张三";
husband.sex = "男"; //貌似有点儿多余
但是如果哪天我们需要对 Husband 进行修改,比如说把它的 age 修改为 String 类型呢?要是你仅仅在一处使用了这个类,那还好。可要是你有几十个甚至上百个这样的地方,你是不是会改到崩溃呢?倘若使用了封装,我们完全可以不必做任何修改,只需稍微改动一下 Husband 类的 setAge()方法就可以了。
public class Husband {
/*
* 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性
*/
private String name ;
private String sex ;
private String age ; /* 改成 String类型的*/
private Wife wife;
public String getAge() {
return age;
}
public void setAge(int age) {
//转换即可
this.age = String.valueOf(age);
}
/** 省略其他属性的setter、getter **/
}
其他地方依旧是这样引用,即保持( husband.setAge(22) )不变。
我们在这里确实能够看出,封装能够让我们更便于修改类的内部实现,并且不需要去修改使用了该类的代码。
我们再看这个好处:封装可以对成员变量进行更精确的控制。
那个 Husband 呢,通常在引用这个对象时不容易出错,然而有时你会迷糊,写成了这样:
Husband husband = new Husband();
husband.age = 300;
或许是因为粗心才写成这样的。你发现了这一情况还算好,要是没发现的话,那就麻烦啦。毕竟谁见过 300 岁的老妖怪呢!
但是通过封装,我们能够避免这个问题。我们可以对 age 的访问入口进行一些控制,例如设置(setter)。
public class Husband {
/*
* 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性
*/
private String name ;
private String sex ;
private int age ; /* 改成 String类型的*/
private Wife wife;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 120){
System.out.println("ERROR:error age input...."); //提示錯誤信息
}else{
this.age = age;
}
}
/** 省略其他属性的setter、getter **/
}
上面都是对 setter 方法进行的控制。实际上,通过封装,我们也能够对对象的出口做出良好的控制。比如,在数据库中,性别通常是以 1、0 的方式来存储的,然而在前台,我们却不能展示 1、0。在此情况下,我们只需在 getter()方法里面进行一些转换就可以了。
public String getSexName() {
if("0".equals(sex)){
sexName = "女";
}
else if("1".equals(sex)){
sexName = "男";
}
return sexName;
}
使用时,只需使用 sexName 就能实现正确的性别显示。同样地,它也可用于依据不同的状态进行不同的操作。
public String getCzHTML(){
if("1".equals(zt)){
czHTML = "+id+")'>启用";
}
else{
czHTML = "+id+")'>禁用";
}
return czHTML;
}
我喝了一口普洱茶,然后对三妹说:“好了,关于封装,我们暂且就聊到这里吧。”
“好的,哥,我懂了。”
参考链接:,整理:沉默王二
GitHub 上被标星 10000 多的开源知识库是《二哥的 Java 进阶之路》,其第一版的 PDF 终于到来了。涵盖 Java 基础语法,还有数组与字符串,以及 OOP 等内容,包含集合框架、Java IO、异常处理等方面,也有 Java 新特性、网络编程、NIO 和并发编程,以及 JVM 等,总计 32 万余字,有 500 多张手绘图,可谓通俗易懂且风趣幽默……详情戳:太赞了,GitHub 上标星 10000+ 的 Java 教程