2.1.3 类及类成员的访问权限
Java封装的一大好处就是保护数据,因此要访问类或封装在类中的数据和代码,必须清楚在什么情况下,它们是可访问的,或者我们如何来限制别人的访问。
一个类总可以访问和调用自己的变量和方法,但这个类之外的程序其他部分是否能访问这些变量和方法,则由该属性和方法以及它们所属类的访问控制符决定。
1.类的访问权限
一个类仅有两个可能的访问权限:默认的和公有(public)的。当一个类被声明为public时,该类可被任何包的代码访问;如果一个类为默认的访问权限,那么仅能由同一包内的其他代码所访问。如下定义的Rectangle类为默认访问权限,因此它只能在本身所在的包内被访问。
class Rectangle{ ... }
2.类成员的访问权限
类成员的访问权限不可能大于类的访问权限。即如果类只能在本包内被访问,那么作为类的成员也最多只能在本包中被访问,就算该成员设定为public也同样受到这个规则的限制。
类成员的可访问性与定义时所用的修饰符private(私有)、default(缺省)、protected(保护)和public(公共)有关。声明为private的类成员仅能在本类内被访问;修饰符在缺省状态,只能被本类和本包访问,声明为protected的类成员可以被本类、本包、本类的子类访问;声明为public的类成员可以被所有包内的类所访问;未用修饰符声明的类成员,则隐含为在本包内可被访问。
为清楚起见,将类成员的可访问性总结在表2-1中。其中,“√”表示允许使用相应的变量和方法。注意,表中列出的类成员可访问性是针对public类的成员。
表2-1 Java类的成员变量和成员方法的访问权限
关于子类的概念在下一节讲解继承性的时候详细讲解。
【例2-1】 创建一个包com和其子包bean,将矩形类Rectangle放入该包中;再创建com.demo包,定义RectangleDemo主类并放入com.demo包中,在主方法中使用com.bean包中的Rectangle类,生成一个Rectangle类的对象,打印该对象的信息。
// 源文件Rectangle.java package com.bean; //本类属于com包的bean子包下 public class Rectangle{ // 该类的权限为public // 私有的成员变量 private double length; private double width; // 求长方形的面积,注意该方法权限 double area(){ return length * width; } /**打印输出,公共的成员方法*/ public void display(){ // 调用当前对象的成员变量 System.out.println("长:" + length + "\t宽:" + width); // 调用当前对象的成员方法 System.out.println("长方形的面积是:" + area()); } } // 源文件RectangleDemo.java package com.demo; // 本类属于com.demo包下 import com.bean.*; // 导入com.bean包中所有的类 public class RectangleDemo{ public static void main (String args[]){ // 调用无参构造方法创建一个长方形对象rect Rectangle rect = new Rectangle(); //rect.width=2; //private不允许类外部调用 //rect.length=4; //private不允许类外部调用 //System.out.println("长方形的面积是:"+rect.area()); // 默认权限不同包的类不能调用 rect.display(); // 调用对象rect的成员方法 } }
可以看出,在Rectangle类内,方法area()使用默认访问,它只能在本包com.bean内被访问。成员变量length和width被赋予了private访问权,这意味着它不能被Rectangle类外的代码访问,所以在RectangleDemo类内不能直接使用length和width,而public方法display()可以允许其他包的类使用。
3.getter、setter方法
上面的程序引出了一个问题,既然私有属性不能外部访问,那么如何给对象中的私有属性赋值呢?
若需要在其他类中访问私有属性,可以通过非私有的setter和getter方法来访问。这样的方法常命名为setXxx()和getXxx(),分别实现对该私有属性的设置和读取操作。如下编写了对私有属性width和length的setter、getter方法。
public void setWidth(double w){ // 设置长方形的宽 width = w; } public double getWidth(){ // 获取长方形的宽 return width; } public void setLength(double l){ // 设置长方形的长 length = l; } public double getLength(){ // 获取长方形的长 return length; }
那么,就可以在其他类中利用这两个方法对私有属性进行操作了。
public class RectangleDemo{
public static void main (String args[]){
Rectangle rect=new Rectangle(); // 声明对象rect并实例化
rect.setWidth(10); // 调用setter方法设置成员变量
rect.setLength(20);
rect.display();
}
}