0

如果 Base 和 Derived 类位于不同的包中,则来自Base的 package-private 成员不应被继承,因此它不应在Derived中不存在,即此类成员将无法通过并且-在任何一种情况下都会产生编译错误!Base obj = new Derived()Derived obj = new Derived()obj.member()

但我看到Base obj = new Derived(),obj.f()是可访问的!

是的,私有成员仍然存在,因为当我创建new Derived()then时new Base(),它的所有私有成员也被创建(在引擎盖下)。但是,如果我将下面代码中的 package-private 更改private ,则会 出现编译错误(隐式存在的)其超类(基类)的私有 (-) 成员。f()obj.f()Base obj = new Derived()

(-)(因为 Base 和 Derived 在不同的包中)

package com.main_pkg;

public class Base {     
    void f() { } // default visibility        
}

package org.another_pkg;

import com.main_pkg.Base;

public class Derived extends Base {         

}

package com.totally.different_pkg;

import org.another_pkg.Derived;

public class DerivedFromDerived extends Derived {

}

最后

import org.another_pkg.Derived;

import com.totally.different_pkg.DerivedFromDerived;

public class Driver {  // Base class is in same pkg as Driver!

    public static void main(String[] args) {
        Base obj1 = new Derived();
        obj1.f(); // f() is visible!

        Base obj2 = new DerivedFromDerived();
        obj2.f();  // f() is visible!
    }
}

您能否制定一个快速简便的实用规则(换句话说,不是在 JLS 和常见的默认可见性定义中)如何理解复杂继承/包组合中的可见性(访问)(我们可能有复杂的层次结构 Base-> Derived->Derived2->Derived3 并且每个类都可以在相同/不同的包中。如何快速查询可访问性?

例如,对于(基类的)受保护成员,“快速猜测”规则非常简单:

  1. 如果Base 和 Driver 在同一个包中(即来自代码Base obj = new Base(); obj.baseProtectedMember(); 编译的任何 Driver 的方法)=> 任何组合都可以工作(Base obj1 = new Derived2(); Derived2 obj2 = new Derived2() 等 -obj1.baseProtectedMember() 并且obj2.baseProtectedMember()是可见的并且可以是称为)。而且我们不在乎其他类在什么包中!
  2. 如果 Base 和 Driver 不在同一个包中(即来自任何 Driver 的方法,代码Base obj = new Base(); obj.baseProtectedMember(); 不会编译)=> 任何组合(参见 1)都不起作用。而且我们不在乎其他类在什么包中!

但是对于包私有成员,我们确实关心哪个层次类在哪个包中,我无法为一般情况制定一个简单可靠的“快速猜测”规则......

PS有趣的旁注:

如果我在上面的代码片段(帖子顶部)中覆盖 Derived 和 DerivedFromDerived 中的方法(将它们保留为包私有),则输出为:

f() from Base called
f() from Base called
4

1 回答 1

1

Base并且Driver在同一个包中,所以Driver可以看到Base的包私有方法。如果您声明Base obj1 = new Derived()Derived obj1 = new Derived()您将不会看到f()。这同样适用Base obj2 = new DerivedFromDerived(),因为如果您将其声明为 a DerivedFromDerived,您将看不到f()

于 2019-01-05T22:11:30.017 回答