为啥受保护的修饰符在 Java 子类中的行为不同?

Posted

技术标签:

【中文标题】为啥受保护的修饰符在 Java 子类中的行为不同?【英文标题】:Why the protected modifier behave differently here in Java subclass?为什么受保护的修饰符在 Java 子类中的行为不同? 【发布时间】:2013-08-09 21:21:38 【问题描述】:

我在两个不同的包中有以下两个类。我的实例方法的访问修饰符受到保护,这意味着相同或不同包中的任何子类都可以访问它吗?但是,在 Eclipse 中,我在第 17 行的子类 Cat 上看到以下消息

The method testInstanceMethod() from the type Animal is not visible 

我的超类和子类代码如下。

package inheritance;

public class Animal 

    public static void testClassMethod() 
        System.out.println("The class" + " method in Animal.");
    
    protected void testInstanceMethod() 
        System.out.println("The instance " + " method in Animal.");
    


package testpackage;

import inheritance.Animal;

public class Cat extends Animal
        public static void testClassMethod() 
            System.out.println("The class method" + " in Cat.");
        
        public void testInstanceMethod() 
            System.out.println("The instance method" + " in Cat.");
        

        public static void main(String[] args) 
            Cat myCat = new Cat();
            Animal myAnimal = myCat;
            myAnimal.testClassMethod();
            myAnimal.testInstanceMethod();
        
    

【问题讨论】:

访问修饰符的范围在this table 中清晰可见。这种情况下的问题是您试图在Animal 上调用testInstanceMethod。假设您将方法命名为meow()(在名为Cat 的类中使用这样的方法是有意义的)。现在很清楚,让您在任何Animal 上调用meow() 是没有意义的。 Animal 可能是 Dog! :-) 【参考方案1】:

受保护的访问修饰符不授予package 访问权限,这意味着同一包中的类不被授予对受保护字段的访问权限。

Protected 确实授予对从包含该字段的基类(继承关系)派生且位于同一包中的类的访问权限。

因此,要满足受保护级别的访问,必须满足两个条件:

    这些类必须在同一个包中。 必须有继承关系。

在您的示例中,仅满足其中一个条件(类之间存在继承关系),但是它们不在同一个包中。

如果您将Animal 移动到与Cat 相同的包中,则代码将编译。

package testpackage;

public class Animal 

    public static void testClassMethod() 
        System.out.println("The class" + " method in Animal.");
    
    protected void testInstanceMethod() 
        System.out.println("The instance " + " method in Animal.");
    

【讨论】:

我在这里接受的答案中发现“内联链接 - ***.com/questions/5416074/…”受保护授予对不同包中子类的访问权限,在这种情况下为什么上面的代码会抛出错误? 我觉得这个答案有点混乱。受保护的修饰符确实 授予包内的访问权限。请参阅this table 以获得清晰的可视化。这里的问题(afaict)是myAnimal 的静态类型是Animal,它不会暴露testInstanceMethod。 (如果您将myAnimal 的静态类型更改为Cat,即使没有将它们放在同一个包中,代码确实也会编译。)

以上是关于为啥受保护的修饰符在 Java 子类中的行为不同?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的权限修饰符

为啥另一个包中的子类不能访问受保护的方法?

实例变量修饰符

protect的简介

为啥受保护的实例成员在不同包的子类中不可见,但受保护的类成员是? [复制]

为啥 Java 允许增加子类中受保护方法的可见性?