Java访问权限修饰符浅析及理解误区

    xiaoxiao2021-12-14  16

    我的第一篇博文~~ 基于个人理解,纯手打,如有不当之处,欢迎指出,谢谢~ Java的访问权限修饰符:public,protected,friendly(默认),privated. 其中 类只能使用public,friendly(缺省). 类的成员变量和方法可以使用public,protected,friendly(默认),privated. 内部类可以使用public,protected,friendly(默认),privated. 下面主要说的是访问权限修饰符在 类的成员变量和方法 的应用: Public:公共访问权限,一个类中被public所修饰的成员变量或方法,能够被所有的类(包括这个类本身)访问. Protected:保护访问权限,一个类中被protected所修饰的成员变量和方法,只能够被同一个包内的类,它的子类,和该类本身所访问. Friendly: 友好访问权限(默认包权限), 使用方式就是:不添加权限修饰符,那么这个类的成员变量或者方法就是Friendly的了.它的成员变量和方法只能够被同一个包内的类,和这个类本身所访问. Privated:私有访问权限,一个类中被privated所修饰的成员变量和方法,只能够被这个类本身所访问.

    这里大家要明确一下"访问",  要弄清楚此时此刻访问的发起者是谁,在一些比较复杂的方法调用中,访问的发起者是不断的变化的.

    下面举个例子,你就会清楚:

    package package1; public class A { public int i=1; private int j=2; public int getValue(){return j;}; } package package2; import package1.A; public class B { public static void main(String[] args) { A a =new A(); System.out.println("在类B里发起访问,访问类A的public变量i ="+a.i); // System.out.println("在类B里发起访问,访问类A的public变量j ="+a.j); j对于类B是privated,无法访问 System.out.println("在类B里发起访问,访问类A的public方法getValue(),得到j ="+a.getValue()); } } 在类B里发起访问,访问类A的public变量i =1 在类B里发起访问,访问类A的public方法getValue(),得到j =2

    分析:类A和类B分别在package1和package2

    所以在类B的main()函数里,访问者是类B:

    它发起了对类A的对象a的i值的访问,   i是public的,所以可以访问.

    它发起了对类A的对象a的j值的访问,   j是privated的,不可以由类B访问.(但是可以由类A自身的方法访问!!)

    它发起了对类A的对象a的方法getValue的调用, 再由getValue()去访问j并返回j的值.所以在这个过程中是这样的: 

    类B----(此时类B是访问发起者)------>对象a的public方法------(此时对象a的getValue()是访问发起者)---->对象a的privated变量.

    上面的示例,我们可以发现,访问发起者是变化的,最终类B成功得到了对象a的privated变量i的值.(在这个例子中必须借助对象a的public方法getValue())

    所以访问的发起者可以这样来说:   发起"访问请求"的代码   的位置,决定了此时的发起者是谁,然后在权限修饰符的作用下,达到封装的效果.

    重点是理解访问的发起者是谁,然后结合最下面给的访问权限修饰符图示,可以写出  封装完善  的代码.

    下面再出一些实例:

    Public: package package1; public class A { public int i=1; private int j=2; public int getValue(){return j; } } package package2; import package1.A; public class B { public static void main(String args[]){ A a = new A(); System.out.println("i="+a.i); System.out.println("j="+a.getValue()); // System.out.println("j="+a.j) 类B不能直接访问j,它是类A中的privated成员变量,会报错,所以注释掉了. } }结果输出为: i=1 j=2

    小结与思考:类A中的i为public,可以被所有类访问. j为privated(所以j不能被直接访问),但是j能被类A中的public方法getValue()访问,所以可以在类B中借助类A的方法getValue()来访问不能直接访问的i.那么你可能会有疑问了:反正最后都允许访问到i,为什么还要绕个弯(多走一步去使用这个类的方法来访问i)? 其实这就是Java的封装,通过为成员变量和方法添加修饰符,可以控制每个类自己希望给别的类看到的和使用的,隐藏不想让外界直接访问的,从类库的开发者和类库的使用者角度来说,这能够保证类库的开发者能够不断修改自己隐藏的内部变量或方法(非public修饰的即可),而不会影响到类库使用者的使用。因为使用者只能使用那些它应该使用的方法。 封装不是一两句话能说明白的,这个小例子只是希望能引导你们去思考Java语言的设计思想...

    Protected

    package package1; public class A { protected int i=1; private int j=2; protected int getValue(){return j; } } package package2; import package1.A; public class B extends A { public static void main(String[] args){ B b =new B(); System.out.println("i="+b.i); System.out.println("j="+b.getValue()); // System.out.println("j="+a.j) 类B不能直接访问j,它是类A中的privated成员变量,会报错,所以注释掉了. } } 结果输出为: i=1 j=2

    小结与思考:类A中的i和方法getValue()为protected,可以被子类或者同一包内的类,和类A本身所访问.不过上面给的例子是类A在包1,类B在包2,问题来了:类B在包2为什么还是能访问类A的protected成员和方法呢?原因就在于 B类是A类的子类.所以这里引出了一个思考点:只要是子类,即使不在同一包内也可以访问protected所修饰的成员变量或者方法.

    Friendly(默认包权限)

    package package2; class A{ int i=1; private int j=2; int getValue(){return j; } } public class B { public static void main(String[] args) { A a = new A(); System.out.println("i="+a.i); System.out.println("j="+a.getValue()); // System.out.println("j="+a.j) 类B不能直接访问j,它是类A中的privated成员变量,会报错,所以注释掉了. } } 结果输出为: i=1

    j=2

    常见误区:

    一个类中privated的成员变量或方法   在别的类中就不能使用了,其实还是可以通过这个类中的非privated方法来访问或调用.就像上面的3个例子那样。

    protected修饰的成员变量或者方法仍然可以在非同一个包内使用,只要你实现了它的子类,通过子类去调用就可以了.

    这2个误区主要是个人没有对访问权限修饰符的描述进行反复咀嚼,如果加上没有实际的代码体验,就更容易产生观念上的误区,从而影响对知识的正确理解和掌握。

    根据上面的内容,得出以下的权限修饰符图表:

    总结:每个访问修饰符的访问范围很容易去记住,但关键是要真正理解它们,才能够灵活的运用.设计出优雅的代码...(这也是我的追求) 如果你正在与别人写的类进行交互:   privated修饰的成员变量不能够被别的类"直接访问",这不代表我们不能就访问它了,我们仍然可以通过这个类中的非privated方法来访问这些变量.(毕竟privated成员变量还是可以被本类的方法访问的).      这就是封装

    个人感悟:类的访问权限修饰符可以确保类的成员变量和方法能够被"正确"地访问,它的应用解决了类库开发者和类库使用者的矛盾。将一些方法public化,也就是允许别的类直接去使用调用或者访问,那些不希望被别的类调用或访问的,则用非public的修饰符来修饰。具体用哪一个修饰符取决于你对这个类的整体用途以及它内部自身的模块化逻辑. 整体来说,Java语言的创始者站在一个更高的角度来解决类之间的协作,通过添加访问权限,以此达到封装的目的.让类库开发者和类库使用者的更加“和谐”.真的是非常优雅的解决方案!

    转载请注明原文地址: https://ju.6miu.com/read-963968.html

    最新回复(0)