封装是面向对象的第一个重要特征,在前面的笔记中已经有所体现。
在看书学习的过程中发现封装和访问修饰符存在密切的联系,所以顺带对访问修饰符做一个大体的总结。
一、封装的两种实现方式。
1.通过包实现封装性
package ClassNotes; class Person { ..... }
包的导入:
1 import ClassNotes.HelloSwing;//导入 2 class Person 3 { 4 int age; 5 } 6 public class T01 7 { 8 public static void main(String[] args) 9 { 10 Person p = new Person(); 11 P.age=12; 12 HelloSwing frame=new HelloSwing();//调用 13 } 14 }
2.通过访问权限实现封装。
1 class Person 2 { 3 private int age; 4 5 } 6 public class T01 7 { 8 public static void main(String[] args) 9 { 10 Person p = new Person(); 11 p.age=12;//错误的,无法给属性赋值 12 } 13 }
(1).通过运用private修饰类、成员变量、成员方法来控制访问权限,从而达到封装的目的。
如何解决上面例子的问题呢?下面给出程序:
1 class Person 2 { 3 private int age; 4 public int getAge() 5 { 6 return age; 7 } 8 9 public void setAge(int age) 10 { 11 this.age = age; 12 } 13 public void print() 14 { 15 System.out.println("我今年:"+age+"岁。"); 16 } 17 } 18 public class T01 19 { 20 public static void main(String[] args) 21 { 22 Person p = new Person(); 23 p.setAge(12); 24 p.print(); 25 } 26 }
(2).很明显,当一个属性被private修饰,使用对象是无法直接调用它的,所以通过创建getter/setter方法来间接为属性赋值,达到封装的目的。有时候我们也在getter/setter方法中加入属性的控制语句,对所赋值的合理性进行判断。
方法一:控制setter()方法
1 class Person 2 { 3 private int age; 4 public int getAge() 5 { 6 return age; 7 } 8 9 public void setAge(int age) 10 { 11 if(age>0&&age<100) 12 { 13 this.age=age; 14 this.print1(); 15 } 16 else 17 { 18 this.age=age; 19 this.print2(); 20 } 21 } 22 public void print1() 23 { 24 System.out.println("我今年:"+age+"岁。"); 25 } 26 public void print2() 27 { 28 System.out.println("您输入的年龄"+age+"岁不符合常理,请重新输入!"); 29 } 30 } 31 public class T01 32 { 33 public static void main(String[] args) 34 { 35 Person p = new Person(); 36 p.setAge(180); 37 } 38 }
方法二:控制print()方法
1 class Person 2 { 3 private int age; 4 public int getAge() 5 { 6 return age; 7 } 8 9 public void setAge(int age) 10 { 11 this.age=age; 12 } 13 public void print() 14 { 15 if(age>0&&age<150) 16 System.out.println("我今年:"+age+"岁。"); 17 else 18 System.out.println("您输入的年龄"+age+"岁不符合常理,请重新输入!"); 19 } 20 } 21 public class T01 22 { 23 public static void main(String[] args) 24 { 25 Person p = new Person(); 26 p.setAge(18); 27 p.print(); 28 } 29 }
当p.setAge(18); 输出:我今年:18岁。
当p.setAge(180); 输出:您输入的年龄180岁不符合常理,请重新输入!
上面的两种方法虽说都达到了目的,但总感觉并没有真正控制赋值范围,后期如果想通了再来修改答案。
(3).**注意:上述是用private封装属性,如果用private封装方法,又该怎么调用该方法呢?
看下面的解决方法:
1 class Person 2 { 3 private void print() 4 { 5 System.out.println("我今年是"+age+"岁。"); 6 } 7 public int getAge() 8 { 9 return age; 10 print();//在类的方法中调用私有方法 11 } 12 public void setAge(int age) 13 { 14 this.age=age; 15 } 16 }
可以看出,访问修饰符private是对类外而言的,而在同一个类中,所有的类成员属性和方法都是互相可见的,也就是说它们能相互访问。
(4).如果我们不想让初始化后的属性值被外界修改时,可以使用构造方法配合私有化setter方法来实现终极封装。
1 class Person 2 { 3 private int age; 4 public Person(int age) 5 { 6 setAge(age); 7 } 8 public int getAge() 9 { 10 return age; 11 } 12 private void setAge(int age) 13 { 14 if(age>0&&age<100) 15 { 16 this.age=age; 17 this.print1(); 18 } 19 else 20 { 21 this.age=age; 22 this.print2(); 23 } 24 } 25 public void print1() 26 { 27 System.out.println("我今年:"+age+"岁。"); 28 } 29 public void print2() 30 { 31 System.out.println("您输入的年龄"+age+"岁不符合常理,请重新输入!"); 32 } 33 } 34 public class T01 35 { 36 public static void main(String[] args) 37 { 38 Person p = new Person(20); 39 } 40 }
因为构造方法只能在实例化对象时调用一次,所以实现了属性值的终极封装。
二、访问修饰符。
常用的访问修饰符有private、protected、public和缺省。
下面的图片适当解释了它们各自的访问权限:
关于访问修饰符,不再详细叙述,以后遇到深层次问题再来讨论。