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使程序连编译都无法通过,而所提示的错误为“属性(name、age)”为私有的,所以不能由对象直接进行访问。为了解决属性必须封装且由必须访问的矛盾,在Java开发中对于私有属性的访问有了以下的明确定义:“只要是被封装的属性,则必须通过setter和getter方法设置和取得。”
为前面类中的私有属性加上setter和getter方法:
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
不考虑上面程序的运行结果,观察结果,可以发现通过setter和getter方法可以是指和取得属性,而在主方法调用时,也是调用了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)在以后的开发中,类中全部属性都必须封装,封装之后的属性必须通过setter和getter进行访问。
(2)面向对象的封装性本省并不是单单指private关键字,为了让读者可以更快的理解封装性,本章只是暂时将封装性的概念进行简单的讲解,读者必须记住的是,用private声明的属性或方法只能在其类的内部被调用,而不能在类的外部被调用。
(3)读者可以发现类中已经有很多的方法,正常情况下,类中的方法直接写上方法名称就可以完成本类中的方法调用,如果在此时非要强调是本类中的方法,也可以在调用时按“this.方法名称()”的形式编写:
public void tell(){
System.out.println(“姓名:” + this.getName() + “,年龄:” + this.getAge());
}
在代码中是否使用this明确的表示当前类中的方法并没有严格的要求。建议在编码时采用这种形式,这样会比较标准一些,在查错时也会更加方便。
程序中的属性进行封装后,在使用类图表示封装属性时就必须按照如下的风格:
属性名称:数据类型
类图如下: