夯实Java基础(二)----面向对象之封装
1、封装介绍
封装封装,见名知意,就是把东西包装隐藏起来,不被外界所看见。
- 像平时用的洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
- 我们使用的电脑,内部有CPU、硬盘、键盘、鼠标等等,每一个部件通过某种连接方式一起工作,但是各个部件之间又是独立的
- 现实生活中,每一个个体与个体之间是有边界的,每一个团体与团体之间是有边界的,而同一个个体、团体内部的信息是互通的,只是对外有所隐瞒。
而Java特性封装:是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节(当然也无从知道),但可以通过该对象对外的提供的接口来访问该对象。类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息向外暴露来进行操作和访问。封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
封装的好处(优点):
- 良好的封装能够增加内聚减少耦合。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合:仅对外暴露少量的方法用于使用
- 通过隐藏对象的属性来保护对象内部的状态,方便修改和实现。(隐藏信息、实现细节)。
- 提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展(将变化隔离,类内部的结构可以自由修改,增加内部实现部分的可替换性)。
- 禁止对象之间的不良交互提高模块化(良好的封装能够减少耦合)。
- 可以对成员变量进行更精确的控制。
- 容易保证类内部数据间的一致性,从而提高软件的可靠性。
2、权限修饰符
提到Java的封装,那么肯定离不开四种权限修饰。Java的权限修饰符共有4种,分别为public
,protected
、缺省
、private
;权限修饰符可以使得数据在一定范围内可见或者隐藏。
权限修饰符共有4种,分别为public,protected、缺省、private;权限修饰符可以使得数据在一定范围内可见或者隐藏。
修饰符 | 本类 | 本包 | 同一个包中 | 任意位置 |
---|---|---|---|---|
private | √ | × | × | × |
缺省 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
这里protected需要注意一下,它的范围应该更大:被protected修饰的成员对于本包和其子类可见,具体参考:https://blog.csdn.net/asahinokawa/article/details/80777302
2、封装的引入
首先我们先来定义一个Person类,并且将其所有的属性用public修饰。代码如下所示:
public class Person {
public String name;//姓名
public int age;//年龄
public String sex;//性别
}
从上面的Person类可以看到,他的所有属性都是用public修饰的,我们在任何地方都可以直接给其属性赋值以及修改值;这就好像你的姓名,年龄,性别都是暴露在外面的,并且在哪里都可以被修改的,而如果Person类有更多的属性,如身份证、电话号码、家庭住址这种比较私密的属性暴露在外面那就不安全了,因为这些属性都是直接暴露在外面的,这就是没有封装的弊端。
我们创建一个Person的实例给他赋值:
Person person=new Person();
person.name="菜徐坤";
person.age=21;
person.sex="woman";
这里我们直接操作属性的值,而封装的思想则是指数据的隐藏,额外暴露接口来对属性进行操作,所以下面来看看怎么在Java中实现封装。
3、封装的实现
如果要使用封装,那么应该怎么操作? 我们只需将成员变量(field)私有化(用private修饰),并且提供公共(public)的get/set方法即可,我们把这种成员变量也称为属性(property)。
public class Person {
private String name;//姓名
private int age;//年龄
private String sex;//性别
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
在使用了封装之后,就不能再用Person类的实例来调用其属性了,会提示该属性是私有化的,不能调用,这样就保证了属性的隐蔽性。我们会提供属性public的getter和setter方法来对属性进行操作。
Person person=new Person();
person.setName("菜徐坤");
person.setAge(21);
person.setSex("woman");
如果你想将年龄设置成 person.setAge(500),你会发现也可以,但是这就不和常理了,人怎么可能活500岁,使用封装我们能够轻松解决这样的问题。我们只需在setAge方法里面添加一些条件即可,如下所示。
public class Person {
private String name;//姓名
private int age;//年龄
private String sex;//性别
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>256 || age <0){
System.out.println("你输入的年龄有误!");
}else{
this.age = age;
}
}
/** 省略其他属性的setter、getter **/
}