2011-12-16 15 views
7

内部リフレクションを使用して内部保護されたクラスをインスタンス化できますが、パッケージレベルの保護を持つ内部クラスはインスタンス化できないのはなぜですか?私はいずれかがパッケージの外にアクセスできるとは思わないでしょう。 2つのクラスが異なるパッケージに含まれていることをJavaリフレクションによるパッケージと保護された保護の比較

package dummy; 

public class ClassContainer { 
    protected static class InnerProtected { 
     public InnerProtected() {} 
    } 

    static class InnerDefault { 
     public InnerDefault() {} 
    } 

    private class InnerPrivate { 
     public InnerPrivate() {} 
    } 
} 


package driver; 

public class DriverClass { 

    public static void main(String[] args) throws Exception { 
     Class.forName("dummy.ClassContainer$InnerProtected").newInstance(); 
     Class.forName("dummy.ClassContainer$InnerDefault").newInstance(); 
     Class.forName("dummy.ClassContainer$InnerPrivate").newInstance(); 
    } 
} 

お知らせ:

は、次の例を考えてみましょう。

メインの最初の行(InnerProtectedをインスタンス化する)が機能します。

(InnerDefaultをインスタンス)2行目は、この例外をスロー:

Exception in thread "main" java.lang.IllegalAccessException: Class driver.DriverClass can not access a member of class dummy.ClassContainer$InnerDefault with modifiers "public" 

クラスをインスタンスでない両方の試みが失敗したドライバは、クラス定義とは異なるパッケージであるため?私が期待するようInnerPrivateが失敗したインスタンス化しようとすると:それは価値がある何のため

Exception in thread "main" java.lang.InstantiationException: dummy.ClassContainer$InnerPrivate 
+0

興味深い質問です。これは、Javaのバグや本当に難解なデザインの決定のようなものです。 – Nayuki

答えて

4

は本当に、javapは、他のメンバーのクラスがパッケージプライベートで一方InnerProtectedは、publicとしてコンパイルされていることを報告し

私はそれが異なるパッケージからClassContainerのサブクラスに見えるようにする必要があると考えています。この場合、VMはアクセス制御ルールを処理できないため、コンパイラレベルで処理されます。

ただし、これらのクラスのコンストラクタ宣言を省略すると、生成されたコンストラクタは予想されるvisililityを持つことになります。つまり、それぞれprotected、デフォルトはprivateです。

+1

はい、JDK 1.00には 'protected'クラスがありません。したがって、クラスファイルもどちらも保護されません。あなたは、同じパッケージからプライベート、そしてローカルの内部クラスにアクセスすることができます。 –