• Java基础知识详解: protected修饰符


    @author: Tobin
    Java初学者,试图用最简单的大白话让自己搞懂一些知识点。

    修饰符modifiers介绍

    学习Java不可避免地接触到一些基本的修饰符。
    修饰符决定了类成员的访问权限,是否能够被其它类所访问。

    • private: 只能被基类访问
    • 无修饰符: 被基类,子类和同package的类访问
    • protected: 在无修饰符的基础上,加了与基类不同包,但是是子类的访问权限,这个访问权限只在子类访问自身的实例时才有,超类的实例还是不能访问的
    • public: 全都可以访问

    下面这个很好地展现了权限的逐层增加。

    protected修饰符详解

    《Java编程思想》对protected的介绍是:被protected修饰的成员对于本包和其子类可见。看了上面的图,我们知道子类可见的意思是不同包的子类也是可见的。总结一下就是:

    • 基类的protected成员是包内可见的
    • 当不在同一个包,但是是其子类也是可以访问protected的成员的。但是有个前提,就是子类只能访问其继承来的protected成员,如果是在子类中初始化一个超类的实例,这个实例是无法访问protected的成员的。
      概念比较抽象,用形象的语言来说。
      包就相当于一个家族。不同包有可能有继承的分支,也有可能毫无关系。类内的成员就相当于资源。
    • private: 私有资源,只能自己使用
    • default: 家族,我自己,我子孙可以用
    • protected: 我可以开放,但是只给自己家族的但是嫁到或者入赘其它家族的后代使用
    • public: 谁都可以用,水资源

    参考几个例子,分析下。
    (1)示例1

    //示例一
    package p1;
    public class Father1 {
        protected void f() {} // 父类Father1中的protected方法
    }
    
    package p1;
    public class Son1 extends Father1 {}
    
    package p11;
    public class Son11 extends Father1{}
    
    package p1;
    public class Test1 {
        public static void main(String[] args) {
            Son1 son1 = new Son1();
            son1.f(); // Compile OK ----(1)
            son1.clone(); // Compile Error ----(2)
    
            Son11 son = new Son11();    
            son11.f(); // Compile OK ----(3)
            son11.clone(); // Compile Error ----(4)
        }
    }
    
    • f方法是超类Father1的,son1和son11虽然是定义不同的包,但是它们的都是Father1的子类,所以都可以访问f方法。此外Test1也在p1包里,所以1和3编译通过。
    • son1和son11的clone()方法都是来自于Father1,但是和f的区别在于,Father的clone()还来自于java.lang.Object,Test1也是Object的子类,这只是说明它可以访问自己继承的clone()方法,即使其它分支继承了相同的方法,它也是不可以访问的。想象一下,家族给其它分支都分配一些资源,即使是相同的,我也不该有权限去访问其它分支的资源。

    (2)示例2

    //示例二
    package p2;
    class MyObject2 {
        protected Object clone() throws CloneNotSupportedException{
           return super.clone();
        }
    }
    
    package p22;
    public class Test2 extends MyObject2 {
        public static void main(String args[]) {
           MyObject2 obj = new MyObject2();
           obj.clone(); // Compile Error ----(1)
    
           Test2 tobj = new Test2();
           tobj.clone(); // Complie OK ----(2)
        }
    }
    
    • Test2继承了MyObject2,clone()方法来源于MyObject2,Test2可以建立自身实例,然后访问clone()方法,2通过
    • 但是作为子类,Test2建立超类实例,直接去访问超类的protected方法是不可以的
    • 想一下,家族已经给我分支资源了,我还要直接向家族拿资源,不该有这个权限
      (3)示例3
    //示例三
    package p3;
    class MyObject3 extends Test3 {
    }
    
    package p33;
    public class Test3 {
      public static void main(String args[]) {
        MyObject3 obj = new MyObject3();
        obj.clone(); // Compile OK ------(1)
      }
    }
    
    • MyObject3继承Test3,两个不在一个包内。Test3作为超类,建立了子类的一个实例,访问子类继承的来自于它的方法,当然它的clone()方法,也是继承自java.lang.Object,这个不管,继承自我的,我是有权限访问的
    • 想象一下,家族给分支资源了,家族是有权限直接访问我给出的资源的

    (4)示例4

    //示例四
    package p4;
    class MyObject4 extends Test4 {
      protected Object clone() throws CloneNotSupportedException {
        return super.clone();
      }
    }
    
    package p44;
    public class Test4 {
      public static void main(String args[]) {
        MyObject4 obj = new MyObject4();
        obj.clone(); // Compile Error -----(1)
      }
    }
    
    • 和示例3的区别在于,此时的clone()方法是子类自身的方法了,来源于MyObject4本身,作为超类是没有权限访问子类的protected成员的
    • 想象一下,分支建立自己的受保护资源,家族没有权限直接访问的
      (5)示例5
    //示例五
    package p5;
    
    class MyObject5 {
        protected Object clone() throws CloneNotSupportedException{
           return super.clone();
        }
    }
    public class Test5 {
        public static void main(String[] args) throws CloneNotSupportedException {
           MyObject5 obj = new MyObject5();
           obj.clone(); // Compile OK ----(1)
        }
    }
    
    • 现在属于同一个包,Test5可以直接访问Myobject5的protected成员
    • 想象一下,同一个家族的资源共享
      (6)示例6
    //示例六
    package p6;
    
    class MyObject6 extends Test6{}
    public class Test6 {
      public static void main(String[] args) {
        MyObject6 obj = new MyObject6();
        obj.clone(); // Compile OK -------(1)
      }
    }
    
    • 即使不在同一个包,1也成立。此处在同一个包,且clone()方法来自于Test6
    • 同一个家族的资源共享
      (7)示例7
    //示例七
    package p7;
    
    class MyObject7 extends Test7 {
        public static void main(String[] args) {
            Test7 test = new Test7();
            test.clone(); // Compile Error ----- (1)
      }
    }
    
    public class Test7 {}
    
    • 超类Test7的方法来自于java.lang.Object,只有java.lang这个包和对应继承了这个clone()方法的Test7才能访问。说白了,方法还是一个方法,但是被不同的子类继承了,就不再是同样的方法了。
    • 看起来是一个家族的,实际上资源是超类从其它家族得到的。其它家族对该资源做了限制,所以不能整个家族都能使用。其次,子类只能访问自身实例的protected资源,没有权限访问超类实例的protected资源。两个条件都不满足。

    其它修饰符

    static
    final
    abstract
    见我Java基础知识系列的其它文章。

    总结

    protected成员,在相同package下,对其它类开放,不同package下,对继承了该类的子类开放(有条件)。其它包的子类没有权限直接创建超类的实例,然后访问超类的protected成员。除了认清楚protected属性,更重要的是要辨别来源,来源决定package是哪个,这是决定访问权限的基础。

    参考文章
    https://blog.csdn.net/ciawow/article/details/8262609。
    https://blog.csdn.net/justloveyou_/article/details/61672133

  • 相关阅读:
    linux下FTP设置技巧
    STM32开发板基础教程(七) ADC with DMA
    linux FTP配置详解
    _crol_小解
    浅谈STM32的DMA模块的使用
    STM32学习笔记(12)DMA初步
    C51中的INTRINS.H:内部函数
    STM32 DMA控制器使用
    KEILC51编译问题ERROR L104: MULTIPLE PUBLIC DEFINITIONS重复定义
    STM32的DMA演示,USART
  • 原文地址:https://www.cnblogs.com/zuotongbin/p/11706068.html
Copyright © 2020-2023  润新知