为什么不能从子类访问受保护的方法?

Why protected method is not accessible from subclass?

考虑以下代码片段:

package vehicle;

public abstract class AbstractVehicle {
    protected int speedFactor() {
        return 5;
    }
}

package car;

import vehicle.AbstractVehicle;

public class SedanCar extends AbstractVehicle {
    public static void main(String[] args) {
        SedanCar sedan = new SedanCar();
        sedan
                .speedFactor();
        AbstractVehicle vehicle = new SedanCar();
        // vehicle //WON'T compile
        // .speedFactor();
    }
}

SedanCarAbstractVehicle 的子 class,其中包含 protected 方法 speedFactor。如果方法 speedFactor 被同一个 class 引用,我可以调用它。当 super class 用于引用时,方法 speedFactor 不可访问。

隐藏方法的原因是什么?

因为 protected 对 class 本身(如私有)及其子 class 实例可见。它不是 public。

例如,

package vehicles;

public abstract class AbstractVehicle {
    protected int speedFactor() {
        return 5;
    }

    public int getSpeed() {
        return 10*speedFactor(); //accessing speedFactor() "privately"
    }
}

package vehicles.cars;

public class SedanCar extends AbstractVehicle {
    @Override
    protected int speedFactor() { //overriding protected method (just to show that you can do that)
        return 10;
    }

    @Override
    public int getSpeed() {
        return 20*speedFactor(); //this is part of the instance (!!!) therefore it can access speedFactor() protected method too
    }
}

package vehicles.main;

public class Main {
    public static void main(String[] args) {
        AbstractVehicle vehicle = new SedanCar();
        int speed = vehicle.getSpeed(); //accessing public method
        vehicle.speedFactor(); //cannot access protected method from outside class (in another package)
    }
}

静态 main() 方法不是实例的一部分,这就是它无法访问受保护方法的原因。

protected 修饰符指定该成员只能在其自己的包内访问(与 package-private 一样),此外,它的 class 在另一个包中的子class .

这就是为什么不能直接调用vehicle对象的main方法里面的方法的原因。

参见:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

您的 SedanCar class 与 AbstractVehicle class 在不同的包中。 protected 方法只能从 相同的包 或子 class 中访问。

SedanCar的情况下:

SedanCar sedan = new SedanCar();
sedan.speedFactor();

您正在从同一个包中调用 protected 方法:好的。 SedanCar 在包 car 中,main() 方法在包 car 中的 class 中(实际上是相同的 class)。

AbstractVehicle的情况下:

AbstractVehicle vehicle = new SedanCar();
vehicle.speedFactor();

您尝试调用 protected 方法,但来自另一个包:不正常。您尝试调用它的 main() 方法在包 car 中,而 AbstractVehicle 在包 vehicle.

基本这样理解:

您有一个 AbstractVehicle 类型的变量,它在另一个包 (vehicle) 中声明。它可能包含也可能不包含 SedanCar 的动态类型。在你的情况下它确实如此,但它也可以包含在另一个包中定义的任何其他 subclass 的实例,例如在 sportcar。并且由于您在包 car 中(main() 方法),您不能调用 vehicle.speedFactor()(这是受保护的 AbstractVehicle.speedFactor())。

回到我的 SCJP Java 1.5 天,我曾经记得的一件事是警惕超类引用变量。现在看到这一点并不令人惊讶,而这让人困惑的一件事是规则是受保护的,对子类或同一个包是可见的。如果它既是子类又是不同的包怎么办?

如果您创建另一个包,并执行

package yetAnotherPackage;

import car.SedanCar;

public class Main {

    public static void main(String[] args) {
        new SedanCar().speedFactor();
    }

}

你会看到

The method speedFactor() from the type AbstractVehicle is not visible

看起来规则刚刚传播。只要你有一个子类并尝试访问子类包中的受保护方法(或者如果没有子类,则访问父类包),你应该是好的。

不同包中的

Subclass 无法使用 superclass 引用从 superclass 访问受保护的方法和受保护的变量。 在 subclass 中访问 superclass 的受保护数据的唯一方法是通过继承

下面是两个代码片段

package nee;
import parentdata.Parent;

class Child extends Parent{

        public void testIt(){
        System.out.println(x);  // able to access protected x defined in Parent
        }

    }


package nee;
import parentdata.Parent;

        class Child extends Parent {

        public void testIt(){
        Parent p=new Parent();
        System.out.println(p.x) //  results in compile time error
        }

    }

在语言规范中 6.6.2.1 访问受保护的会员

令 C 为声明受保护成员 m 的 class。只允许在C的subclassS的body内访问。另外,如果Id表示实例字段或实例方法,则:

If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

有关详细信息,请访问 http://www.jot.fm/issues/issue_2005_10/article3.pdf