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

时间:2009-09-28 15:34:14

标签: java inner-classes

阅读“思考Java”我坚持参加ex:6 of Inner Classes章节。


练习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();
        }
}

Copmiler说:

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

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

4 个答案:

答案 0 :(得分:23)

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

答案 1 :(得分:9)

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

public class COne {

    protected class Inner implements IOne{

        public Inner() { }

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

答案 2 :(得分:0)

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

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...
    }
}  

答案 3 :(得分:0)

问题不在于内部类,而在于继承。

让我们做一些实验。

第一个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调用从inner()类继承的Outer方法。它仍然有效!

package com.ciaoshen.packB;

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

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

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构造函数。

关键点是,当DerivedOuterOuter继承时,您可以想象DerivedClass IS-A Outer,并且它包含Inner班里面作为他的成员。但实际上, DerivedOuter无法直接访问Inner课程,但只能使用他的超级课程Outer