继承时无法访问受保护的内部类
Posted
技术标签:
【中文标题】继承时无法访问受保护的内部类【英文标题】:Can't access protected inner class while inheriting 【发布时间】:2009-09-28 15:34:13 【问题描述】:阅读“Thinking in Java”后,我陷入了内部类章节的 ex:6 中。
练习 6:(2) 在自己的包中创建一个包含至少一种方法的接口。创建一个 类在一个单独的包中。添加实现接口的受保护内部类。在一个 第三个包,从你的类继承,并在一个方法中,返回一个对象 受保护的内部类,在返回期间向上转换到接口。
这是我的代码:
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
从具有受保护内部类的类继承
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();
编译器接着说:
javac CTwo.java
CTwo.java:9: Inner() has protected access in classpack.COne.Inner
IOne io = new Inner();
^
1 error
但是这本书说我可以在派生类中访问受保护的内部类。哪里出错了?
【问题讨论】:
【参考方案1】:错误消息是抱怨构造函数受到保护,而不是类。但是您没有在发布的代码中明确定义构造函数。在这种情况下,according to the JLS,默认构造函数将受到保护(与类相同)。
【讨论】:
这是 Dan Dayer 链接的准确解释:Inner 的构造函数受到保护。但是,构造函数相对于 Inner 是受保护的,而 Inner 相对于 COne 是受保护的。因此,在 CTwo 中可以访问 Inner,因为它是 COne 的子类。 Inner 的构造函数在 CTwo 中不可访问,因为 CTwo 类不是 Inner 的子类!因此,即使 Inner 可以访问,它的默认构造函数也不是。【参考方案2】:您需要为Inner
class
定义一个public
构造函数:
public class COne
protected class Inner implements IOne
public Inner()
public void f()System.out.println("Inner class of COne");
【讨论】:
【参考方案3】:这很清楚。 但这里有一件非常奇怪的事情。
According to the 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...
【讨论】:
您将无法以这种方式在 CTwo 中创建 COne.Inner 的实例。使 COne.Inner 的构造函数受保护有两件事:1) 它将 COne.Inner 的创建限制为包 p1 中的其他类 2) 它允许继承者调用该构造函数作为其构造的一部分。您的示例试图在另一个包中创建 COne.Inner() 的新实例,并且仅仅因为您在从 COne.Inner 继承的类中执行此操作不会使构造函数可访问。但是,当您创建 CTwo 的实例时,将调用您的构造函数。【参考方案4】:问题不在于 Inner 类,而在于继承。
让我们做一些实验。
第一个 Inner
和 Outer
类都具有彼此的完全访问权限。所以下面的代码运行良好。
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
派生自 Outer
。 DerivedOuter
调用继承自 Outer
class 的 inner()
method。它仍然有效!
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
结论,受保护的内部构造函数只能在原始Outer
类范围内访问。任何其他方法(例如:您的 getInner()
方法)都无法访问受保护的 Inner
构造函数。
关键是当DerivedOuter
从Outer
继承时,你可以想象DerivedClass
是一个Outer
,它里面包含一个Inner
类作为他的成员。但实际上,DerivedOuter
无法直接访问Inner
类,而只能使用他的超类Outer
。
【讨论】:
以上是关于继承时无法访问受保护的内部类的主要内容,如果未能解决你的问题,请参考以下文章