封装是 Java 面向对象程序设计的三大特征之一。封装也称为信息隐藏,它将数据和方法的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在方法的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。
封装具有如下优点:
实现专业的分工:将能实现某一特定功能的代码封装成一个独立的实体,让开发人员在需要的时候调用,从而实现了专业的分工。
隐藏信息与实现细节:通过控制访问权限可以将不想让客户看到的信息隐藏起来,提高代码的安全性。例如,某客户的银行的密码需要保密,只能对该客户开放权限。
下面通过两个实例来理解如何实现类的封装。
首先,分析下面的实例,来看没有封装的 Dog 类在调用时会出现哪些问题。
class Dog {
String name; // 声明名字属性
int age; // 声明年龄属性
public void show() { // 定义显示信息的方法
System.out.println("名字是" + name + ",年龄:" + age);
}
}
public class Demo {
public static void main(String[] args) {
Dog d1 = new Dog(); // 实例化1个Dog对象
d1.name = "旺财"; // 为name属性赋值
d1.age = -6; // 为age属性赋值
d1.show(); // 调用对象的方法
}
}
程序的运行结果如下:
名字是旺财,年龄:-6
运行结果输出的年龄为 -6,程序运行没有任何问题,但现实生活中明显不合理。为了避免这种不合理的情况,这就需要用到封装,即不让使用者访问类的内部成员。这时候,就可以使用类的封装机制。
封装是指定义一个类时,使用 private 关键字修饰属性,同时又提供 public 关键字修饰的公有方法以保证外部使用者访问类中的私有属性,即提供设置属性的 setXxx() 方法和获取属性的 getXxx() 方法,对不合理年龄进行过滤限制。
接下来,通过案例来演示封装的实现过程。
class Dog {
private String name; // 声明名字私有属性
private int age; // 声明年龄私有属性
public void setName(String str) { // 设置属性方法
name = str;
}
public String getName() { // 获取属性方法
return name;
}
public void setAge(int n) { // 验证年龄,过滤掉不合理的
if (age < 0) {
System.out.println("年龄不合法...");
} else {
age = n;
}
}
public int getAge() {
return age;
}
public void show() { // 定义显示信息的方法
System.out.println("名字是" + name + ",年龄:" + age);
}
}
public class Demo {
public static void main(String[] args) {
Dog d1 = new Dog(); // 实例化1个Dog对象
d1.setName("旺财"); // 为name属性赋值
d1.setAge(-8); // 为age属性赋值
d1.show(); // 调用对象的方法
}
}
程序的运行结果如下:
年龄不合法...
姓名是旺财,年龄:0
程序中使用 private 关键字将 name 和 age 属性声明为私有的,并对外提供 public 关键字修饰的属性访问器。其中,setName() 设置 name 属性的值,getName() 获取 name 属性的值;同理,getAge() 和 setAge() 方法用于获取和设置 age 属性。
在 main() 方法中创建 Dog 对象,并调用 setAge() 方法传入 -8,在 setAge() 方法中对参数 n 的值进行了检查,由于当前传入的值小于 0,age 属性没有被赋值,仍为默认初始值 0,这样就对无效数据进行了有效的限制,保证了程序的健壮性。