Java:从子类调用超类的受保护方法-不可见?

5
我正在从子类调用超类的受保护方法。为什么这个方法“不可见”?
我已经阅读了一些帖子,比如这个,它似乎与以下内容相矛盾: 超类:
package com.first;

public class Base
{
    protected void sayHello()
    {
        System.out.println("hi!");
    }
}

子类:

package com.second;

import com.first.Base;

public class BaseChild extends Base
{
    Base base = new Base();

    @Override
    protected void sayHello()
    {
        super.sayHello(); //OK :)
        base.sayHello(); //Hmmm... "The method sayHello() from the type Base is not visible" ?!?
    }   
}

https://dev59.com/YmIj5IYBdhLWcg3wuXaN#19949354 - Bax
请访问以下链接以查看与此类似的内容:http://stackoverflow.com/questions/36093187/accessing-protected-member-of-static-class-in-subclass-of-the-parent#comment59830891_36093187 - aioobe
3个回答

11

base是一个普通变量,它在任何方面都不特殊:它不属于类层次结构,也不能通过受保护的访问进行访问。尽管sayHello可以访问Base的受保护成员,但它只能通过继承来访问(因为它不在同一包中: protected关键字允许通过继承和包来访问,请参见这个Oracle教程中的表格)。

通过thissuper进行访问是允许的,因为它们是继承层次结构的一部分。


3
我认为你是唯一一个注意到 base 只是一个变量的人。 - Scary Wombat
2
我觉得我需要更好的术语...我知道我想要表达什么,但我认为有更好被广泛接受的术语,而我现在无法记起。 - Paul Hicks
1
不同之处在于这是同一个类,没有子类参与。请参考dasblinkenlight的引用以获取更具体的细节。 - Paul Hicks
1
@StefanDollase,我的理解与你不同。听起来是正确的,而且与你的例子不同。主要区别在于OP试图使用父类的一个实例,就好像它是this一样。如果它在另一个类中,那么是非常令人惊讶的。 - ChiefTwoPencils
1
正如我所说的,我对私有行为并不感到惊讶,但对受保护行为感到惊讶。所以问题不在于为什么私有允许,而在于为什么受保护不允许。让我们将你提供的使用私有方法的算法示例转换为受保护版本:为什么我不能实现一个算法,它使用当前继承层次结构中另一个实例上的受保护方法?为什么我无法访问BinaryTreeNode中子节点的父类的受保护方法? - Stefan Dollase
显示剩余10条评论

3
这是正确的行为。实际上,在Java语言规范第6.6.2-1节中有一个与你的例子非常相似的示例,注明它不应该编译通过。
访问受保护成员的细节在第6.6.2.1节中详细说明:
6.6.2.1.访问受保护成员 假设C是声明受保护成员的类。只允许在子类S的主体内访问。
此外,如果Id表示实例字段或实例方法,则:
如果访问是通过限定名称Q.Id(其中Q是ExpressionName)进行的,则只有当表达式Q的类型为S或S的子类时才允许访问。
如果访问是通过字段访问表达式E.Id(其中E是Primary表达式),或者通过方法调用表达式E.Id(…)(其中E是Primary表达式)进行的,则只有当E的类型为S或S的子类时才允许访问。
正是最后一段描述了为什么应该拒绝访问。在你的例子中,C是Base,S是BaseChild,变量base的类型E也是Base。由于Base既不是BaseChild也不是BaseChild的子类,因此拒绝访问。

虽然我理解这样可以防止通过 base 访问,但我不明白为什么它允许通过 super 访问。super 不是和 base 是同一类型吗?也许我在 JLS 中漏掉了什么?它在 JLS 的其他部分中被允许吗?我找不到任何允许它的章节。 - Stefan Dollase
1
@StefanDollase 这就是问题所在,super不是一个字段,它是一个关键字,让你可以访问在你的类中被覆盖的基类方法。然而,实际的引用是通过this完成的,而不是通过不同的变量完成的。 - Sergey Kalinichenko

-4

protected 关键字用于在同一程序包中提供可见性。如果子类不属于同一程序包,则无法在子类中访问父类的 protected 方法。


解释下投票反对的原因:“键盘”是一种将字符输入计算机的设备。 “protected is for visibility on the same package” - 在同一个包中,但我离题了。 protected 主要用于授予子类访问权限。 “如果子类不属于同一个包” - 在同一个...“父类的受保护方法对子类不可见。” 不是的。从子类访问是 protected 的全部意义所在。您可能指的是默认可见性,而 protected 访问包括它。 - Johannes Kuhn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接