封装是一个面向对象的术语,其含义很简单,就是把东西包装起来。换言之,成员变量和方法的定义都包装于类定义之中,类定义可以看成是将构成类的成员变量和方法封装起来。
通过限定类成员的可见性,可以使类成员中的某些属性和方法能够不被程序的其他部分访问,它们被隐藏了起来,只能在定义的类中使用,这就是面向对象中实现封装的方式。
尽管技术上允许把成员变量标识为public,但是在实际中最好把所有成员变量都设置为private,如果需要修改、设置或读取该成员变量,开发人员应该使用公共的访问方法。因此任何其他类中的码必须通过调用方法来访问该成员变量,而不是直接使用。
这样有助于提高程序的灵活性,便于代码修改和维护,可以有效避免修改代码“牵一发而动全身”。而且,在成员变量被访问时还可以避免错误,提高程序律壮性,下面这个例子说明了这个问题:
class Desk
{
//height为桌子的高,width为桌子的宽
private int height;
private int width;
//setProperty设置桌子的高和宽,只有输入的值大于0时,才合法
public void setProperty(int i,int j)
{
if(i>0)
{
this.height=i;
System.out.println("桌子的高设置成功");
}
else
System.out.println("桌子的高设置失败");
if(j>0)
{
this.width=j;
System.out.println("桌子的宽设置成功");
}
else
System.out.println("桌子的宽设置失败");
}
}
public class Sample3_29
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Desk d=new Desk();
//必须通过方法设置值,而不能访问
d.setProperty(-100, 200);
}
}
使用封装后不但可以提高健壮性还可以提高灵活性,便于维护代码,例如,由于某种原因,需要将height或weidth设置为String。这时如果没有使用封装,一旦代码修改,所有调用size的代码都将不能使用。
而使用封装只需对设置成员值的方法进行一定的修改,可以使外面的调用者感觉不到变化,将变化限制在一个较小的范围内,例如下面代码将width修改为String,但外界感觉不到变化:
class Desk
{
//height为桌子的高,width为桌子的宽
private int height;
private String width;
//setProperty设置桌子的高和宽,只有输入的值大于0时,才合法
public void setProperty(int i,int j)
{
if(i>0)
{
this.height=i;
System.out.println("桌子的高设置成功");
}
else
System.out.println("桌子的高设置失败");
if(j>0)
{
//将j转化为string类型
this.width=Integer.toString(j);
System.out.println("桌子的宽设置成功");
}
else
System.out.println("桌子的宽设置失败");
}
}
public class Sample3_29
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Desk d=new Desk();
//必须通过方法设置值,而不能访问
d.setProperty(-100, 200);
}
}
代码正确运行,同时,可以体会到封装的优点,在代码发生变化时可以通过修改访问方法,使得修改不影响外界的访问。通过隐藏设计细节,可以把修改代码而造成的负面影响缩小到最小的范围内,这样就可以写出可维护、灵活性和可扩展性很高的代码。
下面总结了Java中封装需要遵顼的规则。
- 用访问限制修饰符保护成员变量,通常是private
- 建立公有的访问方法,强制调用代码通过这些方法访问成员变量