1. 程式人生 > >怎樣繼承一個內部類

怎樣繼承一個內部類

定義一個內部類時,這個內部類會有一個隱式引用(implicit reference)指向外部類的例項。例如下面的程式碼:

class WithInner {
    class Inner {}
}
其實,內部類Inner預設會有一個帶引數的建構函式,我們通過反射來看一下。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
class WithInner {
    class Inner {
        public void getConstructors() {
            for (Constructor<?> cons : getClass().getDeclaredConstructors()) {
                StringBuilder sb = new StringBuilder();
                sb.append("constructor: ").append(cons.getName()).append("(");
                for (Class<?> param : cons.getParameterTypes()) {
                    sb.append(param.getSimpleName()).append(", ");
                }
                if (sb.charAt(sb.length() - 1) == ' ') {
                    sb.replace(sb.length() - 2, sb.length(), ")");
                } else {
                    sb.append(')');
                }
                System.out.println(sb);
            }
        }
    }
}


public class InheritInner {
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        WithInner.Inner i = wi.new Inner();
        i.getConstructors();
    }
}
輸出結果為:constructor: WithInner$Inner(WithInner)
從結果可以看出引數的型別就是就是外部類(outer class),也就是說,構造內部類的時候,必須要給它一個外部類的引用。接下來我們讓InheritInner繼承WithInner.Inner
class WithInner {
    class Inner {}
}
public class InheritInner extends WithInner.Inner {
    public static void main(String[] args) {
    }
}
無法通過編譯:
InheritInner.java:5: an enclosing instance that contains WithInner.Inner is required
public class InheritInner extends WithInner.Inner {
       ^
1 error

報錯資訊提示我們InheritInner需要一個WithInner例項。

那我們給InheritInner加上我們反射出的帶引數的建構函式。照樣編譯通不過,而且會報同樣的錯誤。這是因為語法規定:在繼承內部類的時候,在建構函式中必須要新增enclosingClassReference.super()

class WithInner {
    class Inner {}
}


public class InheritInner extends WithInner.Inner {
    public InheritInner(WithInner wi) {
        wi.super();
    }
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner ii = new InheritInner(wi);
    }
}

OK,編譯通過,執行也正常。但是為什麼要這麼做,我現在也不是很清楚。

參考資料

  • Thinking In Java