14

通读“Thinking in Java”,我陷入了 Inner Classes 章节的 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

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

4

4 回答 4

24

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

于 2009-09-28T15:43:41.903 回答
9

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

public class COne {

    protected class Inner implements IOne{

        public Inner() { }

        public void f(){System.out.println("Inner class of COne");}
    }
}
于 2009-09-28T15:54:10.713 回答
0

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

根据 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...
    }
}  
于 2009-11-10T23:03:20.770 回答
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是从Outer. DerivedOuter调用从类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
    }
}

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

关键是当DerivedOuter从 a 继承时Outer,你可以想象DerivedClassIS-A Outer,它Inner内部包含一个类作为他的成员。但实际上,DerivedOuter没有直接访问 Innerclass 而只能使用他的 super class Outer

于 2017-04-08T05:27:38.873 回答