• 第六章《类的高级特性》第3节:访问修饰符


    在日常生活中,各种信息的公开程度是不一样的。例如:张贴在公告栏中的信息就是完全公开的,任何人都可以看,而有一些具有保密性质的档案就不能被所有人查看,它仅能被拥有权限的特定人员查看。在Java语言中,程序员也可以设置属性、方法以及类的公开程度,专业上把这种公开程度称为“访问度”。

    6.3.1设置属性和方法的访问度

    设置属性和方法访问度很容易,只需要在它们前面加上用于表示访问度的关键字即可。Java语言中,用于表示访问度的关键字有public、protected和private,这3个关键字分别代表了3种不同的访问度。如果在属性和方法前面没有添加任何关键字,这种情况也代表了一种访问度,专业上把这种访问度称为“默认”。因此,Java语言的属性和方法总共就有public、protected、private和默认4种访问度。下面分别讲述这4种访问度的属性和方法在什么情况下能够被访问。

    public:public意为“公开的”,顾名思义,被public关键字所修饰的属性和方法是完全公开的,可以被任何类访问。

    protected:protected意为“受保护的”,被这个关键字所修饰的属性和方法,其访问度要分包内和包外两种情况讨论。为方便讲解,此处先假设有一个A类,A类中定义有被protected关键字修饰的x属性和method()方法。如果是与A在同一个包中的类(也包括A自身),可以随意的访问x属性和method()方法,就如同访问被public关键字所修饰的属性和方法一样。但是不与A在同一个包中的类,仅有A的子类能够访问到x属性和method()方法,因为子类继承了x属性和method()方法。但子类对象仅能访问到自身对象继承而来的x属性和method()方法。如果试图访问其他对象的x属性和method()方法都会导致语法错误,如图6-12所示。

    图6-12 访问受保护属性和方法

    通过图6-12可以看出:B是A的子类,但与A不在同一个包。在B类中,可以访问属于自身对象的x属性和method()方法,虽然这些属性和方法都是从A类中继承而来的。但是,在B类中却不能访问其他A类对象的x属性和method()方法。图6-12中,在B类的test()方法中创建了一个其他的A类对象a,语句“a.x=3;”在编辑器中属性x会被显示为红色,表示不能访问这个属性,而语句“a.method();”下面会出现红色波浪线,这是因为不能访问其他A类对象中受保护的method()方法。如果protected关键字修饰的是静态属性或方法,那么这些静态属性或方法可以被与A在同一个包中的类随意访问,其他包中仅有A的子类能访问这些属性和方法。

    默认:如果在属性和方法前面没有加任何关键字作为修饰,这种情况就属于默认访问度。默认访问度的属性和方法仅能被同一个包中的类(也包括本类自身)访问,任何包外的类都无法访问到这些属性和方法。

    private:private意为“私有的”,被private修饰的属性和方法仅能在本类中被访问,任何其他类中都不能访问到这些属性和方法。

    属性和方法的访问度也能影响到它们的继承性。被public和protected修饰的属性和方法可以被所有子类继承,默认访问度的属性和方法仅能被同一个包中的子类继承,而被private修饰的属性和方法都不能被任何子类继承。在第5章第1小节中曾经讲过“理论上子类继承了父类所有的属性和方法”,之所以强调全部继承父类属性和方法仅是“理论上”的可能,就是因为这些属性和方法的访问度有可能被设置为默认或private。

    此外,方法的访问度还会影响到重写操作。Java语言规定:当子类重写父类的方法时,不能降低访问度。举例来说:如果父类设置某个方法的访问度为public,子类在重写这个方法时,就不能把重写后的方法访问度设为protected、默认以及private,否则会引发语法错误。但子类属性在屏蔽父类同名属性时,不会受到访问度的限制,也就是说:即使无论父类的属性被设置为哪一种访问度,子类的同名属性都可以随意的重新设置它自身的访问度。

    Java语言之所以要对属性和方法设置4种不同的访问度,最主要的作用是为了保护数据的安全性。例如:程序员希望类的某个属性仅能被一部分类访问,就可以把这个属性设置为默认访问度,同时把希望能够访问到这个属性的类与本类放到同一个包中,这样,同一包中的类就可以访问到这个属性,而本包之外的其他类都无法访问它。由此可见,包不仅仅能够解决类同名的问题,还能作为一种“天然屏障”来保护类的属性和方法不被随意访问。

    在实际开发过程中,程序员还经常把一些类的关键属性设置为private,然后提供特定的访问方法让其他类来操作这些属性,这样就能保证它们被设置为合理的数值。例如:定义一个表示圆形的类Circle,该类有一个用来表示圆形半径的radius属性。圆形半径只有在大于0的情况下才属于合理范围。如果没有把radius属性设置为private,那么这个属性就有可能在其他类中被设置一个不合理的值。为了杜绝这种可能性,可以把radius属性的访问度设置为private,然后定义一个访问度为public的setRadius()方法,在该方法中设置radius属性的值,并且在设置值之前完成数据合理性判断。同时,为了能够在其他类中获取radius属性的值,还可以提供一个访问度为public的getRadius()方法,通过这个方法获得radius属性的值。下面的【例06_06】演示了这种编程技巧的完整实现过程。

    【例06_06 为radius属性设置合理数值】

    Circle.java

    1. public class Circle {
    2.     private double radius;//圆形半径
    3.     public void setRadius(double radius) {
    4.         if(radius>0) {//仅在半径大于0的情况下能够完成赋值
    5.             this.radius = radius;
    6.         }else {
    7.             System.out.println("半径值不能小于等于0!");
    8.         }
    9.     }
    10.     public double getRadius() {//获取圆形半径
    11.         return radius;
    12.     }
    13. }

    Exam06_06.java

    1. public class Exam06_06 {
    2.     public static void main(String[] args) {
    3.         Circle circle = new Circle();
    4.         circle.setRadius(-2.0);//为半径设置不合理的值
    5.         circle.setRadius(3.0);//为半径设置合理的值
    6.         double r = circle.getRadius();//获取圆形半径
    7.         System.out.println("圆形半径值为:"+r);
    8.     }
    9. }

    【例06_06】的运行结果如图6-13所示。

    图6-13

    从图6-13可以看出:试图用不合理数值为circle对象的radius属性设置值的操作都不会成功,这是因为用于设置radius属性值的setRadius()方法对参数的合理性做了判断。程序的最后一条语句又通过getRadius()方法获取了circle对象的radius属性值。这个例子很好的展示了如何利用访问修饰符保护关键数据的合理性和安全性,同时还能毫无障碍的获取到关键数据的值。

    6.3.2设置类的访问度

    访问修饰符不仅仅可以用来设定属性和方法的访问度,还能设置类的访问度。普通类的访问度仅可以被设置为public和默认两种。在IDEA中创建的类访问度都是public,如果程序员删除掉了类名称前面的public关键字,那么这个类的访问度就变成了默认。

    访问度为public的类可以被任何其他类访问,而访问度为默认的类仅可以被同一个包下的类访问。因此,程序员试图用import关键字引入其他包下访问度为默认的类都不会成功。可以看出:类的访问度限制了属性和方法的访问度。如果一个类的访问度被设置为默认,那么其他包中的类根本就访问不到这个类,所以即使这个类所有的属性和方法都被设置为public,其他包下的类也不能访问到它们。

    类的访问度还能影响到Java源文件的命名。大部分情况下,一个Java源文件中都只有一个类,并且源文件的名称与类的名称相同。但实际上,Java语言允许在一个源文件中定义多个类,但这些类当中最多只能有1个类的访问度被设置为public,并且源文件的名称也必须与这个public类的名称保持一致,也就是说:public类的名称直接决定了源文件的名称。如果一个源文件中没有任何一个类的访问度为public,那么这个源文件可以在命名规则允许的情况下随意命名。如果一个源文件中定义了多个类,那么对这个源文件进行编译后将会生成多个字节码文件,并且这些字节码文件的名称与源文件中的每一个类一一对应。例如:一个源文件中定义了A、B、C三个类,那么源文件被编译后,会生成名为A、B、C的三个字节码文件。

    除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

  • 相关阅读:
    View 的四种 OnClick 方式
    [附源码]Python计算机毕业设计大学生社团管理系统
    [SWPUCTF 2018]SimplePHP
    shiro反序列化漏洞的原理和复现
    测试22222
    系统集成项目管理工程师认证高频考点:编制项目范围管理计划
    基于深度学习的端到端语音识别时代
    【前端】子元素加margin,父元素div高度计算错误--margin越界
    8.稳定性专题
    项目实战第三十三讲:标准中心-属性体系
  • 原文地址:https://blog.csdn.net/shalimu/article/details/128033610