Java入门系列之访问修饰符作用范围

前言

本节只讲解学习Java中访问修饰符一些需要注意的地方或者从概念上不太好理解我们会通过实际例子来说明,若有错误之处,还请批评指正。欢迎大家在评论区纠错,或者可以把你想了解的评论在底下之后我会尽可能的更新的

访问修饰符

Java默认(Default)访问修饰符权限和C#中类似(在C#中准确的说嵌套在其他类中默认可以为私有,如果直接在命名空间声明的类或结构体可以是public,也可以是internal,但一定不是私有,这里请注意), 如果不提供任何访问修饰符,那么该类将具有包访问权限 ,比如如下在包com.company下创建不带访问修饰符的Person,然后再在该包中创建Person1,在该类中我们可以初始化Person

 
package com.company; class Person { } 
 
package com.company; public class Person1 { public void InitialPerson(){ new Person(); } } 

但是接下来我们再创建一个包com.company1,在其包下通过Person2则不能初始化Person,此时必然会出现编译错误

 
package com.company1; import com.company.Person; public class Person2 { public void InitialPerson(){ new Person(); } } 

 

对于private私有修饰符则没有太多要讲解的了,除了包含该成员的类外,其他任何类都无法访问此类成员,Java中比较难理解的是protected修饰符, 该访问修饰符无论是Java还是C#主要用来处理继承的概念,凭借我们对C#的理解,这里我们认为是本包任何类以及实现该类的子类(不管子类是否在本包中还是其他包中) ,这种说法是完全正确的吗?子类在同一包中肯定可以访问,我们讨论在不同包中的情况会略显复杂一些,首先我们在包com.company定义Animal类,而在包com.company1中定义Tiger类,同时定义一个访问修饰符为protected的动物叫的方法如下:

 
package com.company; public class Animal { protected void Shout(){ System.out.println("Animal"); } } 
 
package com.company1; import com.company.Animal; public class Tiger extends Animal { } 

接下来我们再在包com.company中定义一个类,然后在该类中定义方法,将上述位于不同包中的Animal和Tiger类作为参数变量,此时可以访问叫的方法

 
package com.company; import com.company1.Tiger; public class OtherAnimal { public void OtherMethod(Animal animal, Tiger tiger) { animal.Shout(); tiger.Shout(); } } 

然后我们再在Tiger子类定义一个方法,无论是通过当前实例引用还是直接通过super关键字调用,都可以调用基类的叫方法

 
package com.company; import com.company1.Tiger; public class OtherAnimal { public void OtherMethod(Animal animal, Tiger tiger) { animal.Shout(); tiger.Shout(); } } 

当然若我们在基类Animal中定义方法通过其基类变量访问叫的方法毫无疑问也是可以的,即使将叫的方法设置为私有的,因为在其基类内部

 
public void AnimalMethod(Animal animal) { animal.Shout(); } 

若我们在子类Tiger中再定义一个方法,将Tiger作为变量传递进去,此时也是可以访问基类的叫方法

 
public void tigerMethod1(Tiger tiger) { tiger.Shout(); } 

已经列举如上诸多情况,那是不是就说明在子类中一定能访问到叫方法呢?当然不是,如下两种情况则是无效的,会出现编译错误。

当在基类包外直接引用基类变量访问无效

我们在子类中再定义一个方法,直接引用基类的变量,然后访问叫方法,此时将无效。因为protected具有包访问权限,使得直接访问基类受保护成员变为私有或者说直接引用基类变量,无法判断其类型,因为可能在运行时是基类中的其他子类型,这么讲是否会更妥当一点。

 
public void tigerMethod2(Animal animal) { //发生编译错误 animal.Shout(); } 

当在子类包中的非子类直接引用子类变量访问无效

我们在子类所在包中再定义一个类,然后引用子类变量访问叫方法,此时将无效。因为子类从其基类继承受保护的成员,此时会使它们对非子类私有:

 
package com.company1; public class Tiger1 { public void tiger1Method(Tiger tiger){ //发生编译错误 tiger.Shout(); } }  

总结

有一部分文章对protected的总结是:本包任何类以及实现该类的子类(不管子类是否在本包中还是其他包中),这种说法不能说错误,只能说意思比较隐晦,因为直接读这段话可能就只考虑了在子类中通过子类实例或直接通过关键字super调用基类的受保护的成员,而可能会欠缺对非子类和直接通过基类引用受保护的成员的考虑。

protected修饰符无论是Java亦或是C#具有两层概念访问权限的组合,一是基于程序集(C#)、包(Java)权限、二是继承权限。

所以对于Java的protected访问权限可总结为:本包任何类以及实现该类的子类,无论子类位于本包还是不同包,但对基类外部包直接访问私有,同时对外部包中非子类私有。

最后送正在Java这条路上填坑的伙伴们一波福利,平台原因没有办法直接发布,感兴趣的话可以直接扫描下方二维码添加一下公众号的VX就可以领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大老二在不在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值