阅读“思考Java”我坚持参加ex:6 of Inner Classes章节。
练习6:(2)在自己的包中创建一个至少包含一个方法的接口。创建一个 在一个单独的包中的类。添加一个实现接口的受保护内部类。在一个 第三个包,继承自您的类,并在方法内返回一个对象 受保护的内部类,在返回期间向上转换为接口。
这是我的代码:
接口
package intfpack;
public interface IOne{
void f();
}
具有实现接口的受保护内部类的类
package classpack;
import intfpack.*;
public class COne{
protected class Inner implements IOne{
public void f(){System.out.println("Inner class of COne");}
}
}
从具有受保护内部类的类继承
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
但是这本书说我可以在派生类中访问受保护的内部类。错误在哪里?
答案 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)
问题不在于内部类,而在于继承。
让我们做一些实验。
第一个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
调用从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
构造函数。
关键点是,当DerivedOuter
从Outer
继承时,您可以想象DerivedClass
IS-A Outer
,并且它包含Inner
班里面作为他的成员。但实际上, DerivedOuter
无法直接访问Inner
课程,但只能使用他的超级课程Outer
。