权限修饰符的理解

事情是这样的:
今天看到了一句话,说的是“抽象类的抽象方法可以用 public / protected / default 访问修饰符来修饰;接口的抽象方法默认是 public 访问修饰符,并且不能使用其他访问修饰符 ”,我就纳闷了同样是抽象方法为什么支持的访问修饰符却不一样呢?

网上说这是思想,这是规定,一时之间让人无法理解。
我首先想到的是,是不是我对4个访问修饰符的作用范围理解的不透彻呢,所以我决定先写个demo做一个权限修饰符的比较(结果确实是没有理解透彻,但这并不是本问题的答案,没有理解透彻的部分后面会展开)

这里先说一下如何理解吧,通过使用场景的方式。
根据网上所说“接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,主要用于实现代码的重用
针对前一句,项目人员A写了个API模块,里面声明了一些接口,打包后供项目人员B在业务模块中去实现,如果A用默认修饰符修饰接口里的抽象方法的话,那么B必然不可能访问得到该抽象方法,更不用说去重写了。
因为接口里不能使用public以外的访问修饰符,所以接下来用抽象类来代替该业务场景

public abstract class UserApi{
    
    
    abstract void login();
}

然后在另一个模块下对该接口进行实现,发现报错了。

A去写接口,目的就是让B去实现,但是根据上面的测试发现,如果可以在接口中使用default访问修饰符的话,那么B就无法对其进行实现,这显然不符合我们的初衷,而且也没有使用的必要。抽象类的使用场景这里不做尝试。

接下来是刚才的理解误区,为什么不同包中的子类无法访问父类的protected成员?
网上搜访问修饰符作用范围可以搜到大致长成下面这样的总结,在写demo期间发现我的红色框框的位置报了错
在这里插入图片描述
代码如下:

public class Father {
    
    

    public void m1() {
    
    
    }

    protected void m2() {
    
    
    }

    void m3() {
    
    
    }

    private void m4() {
    
    
    }

}

结果发现不同包下的子类居然无法访问到其父类的protected方法…很尴尬
在这里插入图片描述
这样的结果和不同包下的无关类的结果一模一样
在这里插入图片描述
最后得知,是使用的方式有问题,一张图确实可以把访问权限的作用范围说得明明白白,但不理解其访问方式的话还是会出现上面这样的问题的,正确的不同包下的子类的代码如下
在这里插入图片描述
附上访问权限的相关代码供大家玩耍
本包下:

package com.test;

public class Father {
    
    //若不声明为public,则不同包下子类访问不到,无法继承

    public void m1() {
    
    
    }

    protected void m2() {
    
    
    }

    void m3() {
    
    
    }

    private void m4() {
    
    
    }

    //本类下访问
    public void m() {
    
    
        m1();
        m2();
        m3();
        m4();
        //若方法m1m2m3m4都为static类型,则各类的m方法中通过Father.的方式也可以达到相同结果
    }
}

class SonInTheSamePackage extends Father {
    
    

    //相同包下子类访问
    public void m() {
    
    
        m1();
        m2();
        m3();
        m4();//Father里被private修饰的方法报错
    }
}

class UnrelatedClassInTheSamePackage {
    
    

    //相同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m1();
        father.m2();
        father.m3();
        father.m4();//Father里被private修饰的方法报错
    }
}

其他包下:

package com.test2;

import com.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        m1();
        m2();
        m3();//Father里被默认修饰符修饰的方法报错
        m4();//Father里被private修饰的方法报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m1();
        father.m2();//Father里被protected修饰的方法报错
        father.m3();//Father里被默认修饰符修饰的方法报错
        father.m4();//Father里被private修饰的方法报错
    }
}

最后还有一个疑问,为什么不同包下子类,通过new Father()去访问m2()会失败(即上述我的理解误区),但是m2被修饰为静态的话,却能够访问成功呢(修饰为静态后类名.静态方法或实例对象.静态方法去访问都能成功,这相对于前者失败的情况来说,是为什么呢(不过不同包下的无关类依旧会访问失败))
本包下:

package com.test;

public class Father {
    
    

    protected static void m2() {
    
    
    }

}

其他包下:

package com.test2;

import com.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//不报错
        Father.m2();//不报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        Father.m2();//报错
    }
}

其实还是使用方式的问题,子类下访问应该去new子类对象然后访问(或者直接调用)!而不是在子类new父类对象再去访问!
但无关类去new子类对象或是父类对象然后访问,得到的结果是一样的
本包下:

package com.example.demo.test;

public class Father {
    
    

    protected void m2() {
    
    
    }

}

其它包下:

package com.example.demo.test2;

import com.example.demo.test.Father;

class SonInDifferentPackage extends Father {
    
    

    //不同包下子类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        SonInDifferentPackage son = new SonInDifferentPackage();
        son.m2();//不报错
        m2();//不报错
    }
}

class UnrelatedClassInDifferentPackage {
    
    

    //不同包下无关类访问
    public void m() {
    
    
        Father father = new Father();
        father.m2();//报错
        SonInDifferentPackage son = new SonInDifferentPackage();
        son.m2();//报错
    }
}

写的有点啰嗦了,反正就是那几种情况来回尝试,望多多包涵!

猜你喜欢

转载自blog.csdn.net/weixin_44463178/article/details/108765610
今日推荐