inheritance时无法访问受保护的内部类

通过“Thinking in Java”阅读我坚持使用ex:6 of Inner Classes章节。


练习6:(2)在自己的包中创建一个至少包含一个方法的接口。 在单独的包中创建一个类。 添加一个实现该接口的受保护内部类。 在第三个包中,inheritance自您的类,并在方法内部返回受保护内部类的对象,在返回期间向上转换为接口。


这是我的代码:

IOne.java

接口

package intfpack; public interface IOne{ void f(); } 

COne.java

具有实现接口的受保护内部类的类

 package classpack; import intfpack.*; public class COne{ protected class Inner implements IOne{ public void f(){System.out.println("Inner class of COne");} } } 

CTwo.java

从具有受保护内部类的类inheritance

 package thirdpack; import classpack.*; import intfpack.*; public class CTwo extends COne{ public IOne getInner(){ IOne io = new Inner(); return io; } public static void main(String[] args){ CTwo ct = new CTwo(); ct.getInner(); } } 

Copmiler说下:

 javac CTwo.java CTwo.java:9: Inner() has protected access in classpack.COne.Inner IOne io = new Inner(); ^ 1 error 

但是这本书说我可以在派生类中访问受保护的内部类。 哪里出错?

错误消息抱怨受保护的构造函数,而不是类。 但是您没有在发布的代码中明确定义构造函数。 在这种情况下, 根据JLS ,默认构造函数将受到保护(与类相同)。

您需要为Inner class定义一个public构造函数:

 public class COne { protected class Inner implements IOne{ public Inner() { } public void f(){System.out.println("Inner class of COne");} } } 

这很清楚。 但这是一个非常奇怪的事情。

根据JLS,如果CTwo扩展了COne.Inner,它应该访问Inner的受保护构造函数,但实际上它没有……见下文。

 package p1; public class COne { public static class Inner { protected Inner() {} } } package p2; public class CTwo extends COne.Inner { public void getIface() { new COne.Inner(); // Compile time error anyway with the same complains: // "Inner() has protected access in p1.COne.Inner" // ...unlike my expectations... } } 

问题不在于内部类而是inheritance。

我们来做一些实验。

First InnerOuter类都可以完全访问彼此。 所以下面的代码运行良好。

 package com.ciaoshen.packA; public class Outer { protected class Inner { public void foo() { System.out.println("Hello Ronald!"); } } protected Inner inner() { return new Inner(); } public static void main(String[] args) { new Outer().inner().foo(); // Output: Hello Ronald! } } 

现在在另一个包中, DerivedOuter派生自OuterDerivedOuter调用从Outer类inheritance的inner()方法。 它仍然有效!

 package com.ciaoshen.packB; class DerivedOuter extends Outer { public static void main(String[] args) { new DerivedOuter().inner().foo(); // Output: Hello Ronald! } } 

但是当我覆盖DerivedOuter类中的inner()方法时,会发生相同的错误!

 package com.ciaoshen.packB; class DerivedOuter extends Outer { @Override public Inner inner() { // this is not the inner() of Outer class. BOOM! return new Inner(); } public static void main(String[] args) { new DerivedOuter().inner().foo(); // ERROR: Outer.Inner() has protected access in Outer.Inner } } 

结论,受保护的Inner构造函数只能在原始的Outer类范围内访问。 任何其他方法(例如:您的getInner()方法)都无法访问受保护的Inner构造函数。

关键点在于,当DerivedOuterinheritance自Outer ,您可以想象DerivedClass IS-A Outer ,并且它包含一个Inner类作为其成员。 但事实上, DerivedOuter没有直接访问Inner类,但只能使用他的超类Outer