什么是封装
封装,是面向对象编程的核心思想之一,指的就是将描述某种实体的数据和基于这些数据的操作集合到一起,形成一个封装体。
举个栗子:
其实生活中就有很多封装的案例。以电视机为例,每一台电视机的内部都有很多线路和零件,制造商为了减少零件老化会给零件外面涂上防氧化涂层,为了避免人为破坏,保证零件的完整性,制造商会用外壳把内部器件封存起来,而我们想要看电视就通过遥控器进行操作。隐藏了内部细节,对外只提供简单的操作入口,这就是电视机的封装。
java的封装原理和电视机的封装类似。
如下图所示:我们先创建了一个用户类User,并给了一个age属性。
package encapsulation;
/**
* 用户类
*/
public class User {
int age;
}
接着我们再创建一个用户测试类UserTest,并创建一个User类的对象user
package encapsulation;
/**
* 用户测试类
*/
public class UserTest {
public static void main(String[] args) {
// 创建User类的对象
User user = new User();
// 读取年龄值【get】
System.out.println("该用户的年龄为:" + user.age);
// 修改年龄值【set】
user.age = 18;
// 读取年龄值【get】
System.out.println("该用户的年龄为:" + user.age);
// 修改年龄值【set】
user.age = -100;
// 读取年龄值【get】
System.out.println("该用户的年龄为:" + user.age);
}
}
观察代码,我们可以看到,对于当前程序来说,User类中的age属性可以在外部类中随意的被访问,随意的被修改赋值,甚至是不符合现实逻辑的值,哪怕我们给age属性赋值-100,程序也不会报错,这样就导致了User中的部分属性不安全,这也是当前程序的一个缺陷。
由此也就引出了对类进行封装的思想。封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。
封装的步骤
- 使用private关键字对成员变量进行修饰,使所有属性私有化。private表示私有的,修饰的所有数据只能在本类中访问。
- 对外提供简单的操作入口,也就是说以后外部程序要想访问这个类的属性,必须通过这些简单的入口进行访问。
- 对外提供两个公开的方法,分别是set和get方法。
- 以后操作入口变成了只能通过set和get方法进行访问
- 想修改属性,调用set方法
- 想读取属性,调用get方法
- 同时在set方法和get方法执行过程中可以进行安全过滤。 - set方法的命名规范
//格式:
public void set+属性名首字母大写(形参){
this.属性名=形参;
}
//示例:
public void setAge(int age){
this.age=age;
}
- get方法的命名规范
//格式:
public 返回值类型 get+属性名首字母大写(){
return 属性名;
}
//示例:
public int getAge(){
return age;
}
注意事项:
- getter和setter方法没有static关键字修饰。
- set方法没有返回值,因为set方法只负责修改属性值。
- get方法有返回值,因为get方法要返回查询的属性值。
- getter和sett方法调用格式:对象名.方法名(实参);
这时我们再来看看封装后的代码,如果设置年龄属性不切合实际的数值,会打印“您提供的年龄不合法”合理的进行了安全过滤。
package encapsulation;
/**
* 用户类
*/
public class User {
private int age;
public void setAge(int age) {
if(age<=0||age>150) {
System.out.println("您提供的年龄不合法!");
}
return;
}
public int getAge() {
return age;
}
}
package encapsulation;
/**
* 用户测试类
*/
public class UserTest {
public static void main(String[] args) {
// 创建User类的对象
User user = new User();
// 修改年龄值
user.setAge(-100);
// 读取年龄值
System.out.println("该用户的年龄为:" + user.getAge());
}
}
封装的好处
1、封装之后,对于该事物来说,看不到这个事物比较复杂的那一面,只能看到该事物简单的那一面。复杂性封装,对外提供简单的操作入口。
2、封装之后才会形成真正的"对象",真正的“独立体"。
3、封装就意味着以后的程序可以重复使用。并且这个事物适应性比较强,在任何场合都可以使用。
4、封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。
注意事项:
- 封装和有参构造不冲突,两者可以同时使用。虽然属性被private关键字修饰变成了只能被内部类访问的变量,但不影响使用有参构造方法来给对象赋值,因为有参构造方法本身就是内部类中的一个方法,我们创建对象时先调用有参构造方法,把要赋的值传递到有参构造方法的形参,有参构造方法载给属性赋值。不过查询属性还是要用到getter方法。
- toString()方法也不和封装冲突,因为输出对象名自动调用toString()方法,自动输出方法里的代码体。