1.1 封装性

封装性是面向对象的第一大特性,所谓的封装性就是指外部不可见,那么为什么要有封装性呢?观察一下程序的问题:

class ClassDemo03{

public static void main(String[] args) {

Person p = new Person();

p.name = "张三";

p.age = -12;

p.tell();

}

}

运行结果:

姓名:张三,年龄:-12

在程序中age赋值为-12,这明显是不合法的数据,下面会有如何控制它的输出。

封装的格式如下:

为属性封装:private 属性类型 属性名称;

为方法封装:private 方法返回值 方法名称(参数列表){}

为程序加上封装属性:

class Person1 {

private String name;

private int age;

public void tell() {

System.out.println("姓名:" + name + ",年龄:" + age);

}

}

class EncDemo01{

public static void main(String[] args) {

Person1 p1 = new Person1();

p1.name = "张三";

p1.age = 12;

p1.tell();

}

}

运行结果:

Exception in thread "main" java.lang.Error: Unresolved  compilation problems: 

The field Person1.name is not visible

The field Person1.age is not visible

加上private使程序连编译都无法通过,而所提示的错误为“属性(nameage)”为私有的,所以不能由对象直接进行访问。为了解决属性必须封装且由必须访问的矛盾,在Java开发中对于私有属性的访问有了以下的明确定义:“只要是被封装的属性,则必须通过settergetter方法设置和取得。”

为前面类中的私有属性加上settergetter方法:

class Person1 {

private String name;

private int age;

public void tell() {

System.out.println("姓名:" + name + ",年龄:" + age);

}

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;

}

}

class EncDemo01{

public static void main(String[] args) {

Person1 p1 = new Person1();

p1.setName("张三");

p1.setAge(-12);

p1.tell();

}

}

运行结果:

姓名:张三,年龄:-12

不考虑上面程序的运行结果,观察结果,可以发现通过settergetter方法可以是指和取得属性,而在主方法调用时,也是调用了setter()方法进行内容的赋值,也就是说如果想对设置进去的值进行检查,则只需要在setter方法出检查即可。

setter方法处加上检测代码:

class Person1 {

private String name;

private int age;

public void tell() {

System.out.println("姓名:" + name + ",年龄:" + age);

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

if (age >= 0 && age < 130) {

this.age = age;

}

}

}

class EncDemo01{

public static void main(String[] args) {

Person1 p1 = new Person1();

p1.setName("张三");

p1.setAge(-12);

p1.tell();

}

}

运行结果:

姓名:张三,年龄:0

因为程序中在setter方法处加入了验证代码,所以如果设置的年龄数值不正确,则不会把值赋给age属性,所以程序运行结果会显示默认值0

关于private的补充说明:

(1)在以后的开发中,类中全部属性都必须封装,封装之后的属性必须通过settergetter进行访问。

(2)面向对象的封装性本省并不是单单指private关键字,为了让读者可以更快的理解封装性,本章只是暂时将封装性的概念进行简单的讲解,读者必须记住的是,用private声明的属性或方法只能在其类的内部被调用,而不能在类的外部被调用。

(3)读者可以发现类中已经有很多的方法,正常情况下,类中的方法直接写上方法名称就可以完成本类中的方法调用,如果在此时非要强调是本类中的方法,也可以在调用时按“this.方法名称()”的形式编写:

public void tell(){

System.out.println(姓名: + this.getName() + ,年龄: + this.getAge());

}

在代码中是否使用this明确的表示当前类中的方法并没有严格的要求。建议在编码时采用这种形式,这样会比较标准一些,在查错时也会更加方便。

程序中的属性进行封装后,在使用类图表示封装属性时就必须按照如下的风格:

属性名称:数据类型

类图如下: