1.笼统介绍
网上关于protected关键词的解释为:被 protected 修饰的成员对于本包和其子类可见。这个说法精炼但不够具体。
更具体的说法(菜鸟教程)为:
- 基(父)类的 protected 成员是包内可见的,并且对子类可见;
- 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。
懂的人看到这段自然就懂了,但新手难免还会掉进各种坑里。这里索性就直接举例,用具体的例子来说明哪种情况可以,而哪种情况不可以
2.具体例子
a.基类的 protected 成员是包内可见的,并且对子类可见
情况1:同属于一个包内,在Test中创建ExamClass1的实例对象。发现在Test中可以访问实例对象中被protected修饰的变量和方法。
情况2:不在一个包内,import之后,虽然可以创建实例化对象。但是无法访问实例化对象中被protected修饰的变量和方法
特殊情况:Test和ExamClass1没有声明包,所以他们实际上都在默认包里,此时Test中可以访问ExamClass1的实例化对象中被protected修饰的变量和方法
请不要研究这种情况,在我尝试时发现,即使Test和ExamClass1不在一个Module里,但在不声明包的情况下,仍然可以调用,这是一个很混乱的情况。
请记住,无论何时,都不要使用默认包,默认包不符合java规范
b.基类的 protected 成员是包内可见的,并且对子类可见
情况1:父类和子类在同一包内时,肯定可以互相访问,不再演示这种情况。和a.情况1类似
情况2:父类和子类不在同一包内,在子类里可以使用父类被protected修饰的变量以及方法。
图中的name和speak()均是父类中被protected修饰的变量或方法。但是可以在子类中正常调用
c.若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。
情况1:字面意思
如图,子类的main方法中创建子类的实例化对象,就可以直接访问其继承过来的protected方法。但是创建父类实例化对象,就不能访问
情况2:在Test中创建子类实例化对象,发现不可以调用方法
因为这个speak()方法归根到底是来自ExamClass1,因为只有和这个类在同一个包的对象或者他的子类才可以调用。因此情况1可以调用,而情况2不可以调用
情况3:在子类中重写protected方法
如图,我在ExanClass2中重写了其父类的speak方法,然后在Test中重新调用,发现可以调用了。因为这个时候,我调用的这个方法实际上是已经重写后的方法。而重写的这个方法,它来自ExamClass2,因此与ExamClass2在同一个包的其他class可以调用,ExamClass2的子类也可以调用
参考
Java protected 关键字详解 | 菜鸟教程
https://www.runoob.com/w3cnote/java-protected-keyword-detailed-explanation.html
我已经列举了大部分常见的情况,其中菜鸟网中还有些不太常见的方法。
其中实例4以后的例子我个人觉得就比较罕见(正常情况不会这么写),了解其思想即可:确定这个方法来自于哪个类,因此只有这个类所在的包 以及 这个类的子类 才被允许访问