プログラミング言語Javaでは、スーパークラスのprivateフィールドはサブクラスへ継承(inherited by)されず、原則としてスーパークラス外部からはアクセスできない。ただし特定の条件下において、サブクラスからスーパクラスprivateフィールドへのアクセスが可能となる。*1
class AccessibleTrick { // スーパークラス static class Superclass { private int secret = 42; } // スーパークラスを継承したサブクラス static class Subclass extends Superclass { void spySecretValue() { int value; value = this.secret; // NG: コンパイルエラー // error: secret has private access in Superclass value = ((Superclass)this).secret; // OK: スーパークラスprivateフィールドにアクセス } } public static void main(String[] args) { Subclass obj = new Subclass(); obj.spySecretValue(); } }
対象となるスーパークラスSuperclass
/サブクラスSubclass
ともに、同じクラスAccessibleTrick
の入れ子クラス(nested class)*2であるときに限ってprivateフィールドへのアクセスが許可される。Java Language Specification, Java SE 8 Editionより一部引用。
Chapter 6. Names, 6.6.1. Determining Accessibility
- A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:
- (snip)
- Otherwise, the member or constructor is declared
private
, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
A
Chapter 8. Classes, 8.3. Field Declarationsprivate
field of a superclass might be accessible to a subclass - for example, if both classes are members of the same class. Nevertheless, aprivate
field is never inherited by a subclass.
ノート:本記事はJLS §8.3 "A private field of a superclass might be accessible to a subclass"を動機としているため、継承関係にあるクラス間のprivateフィールドにフォーカスしている。JLS §6.6.1に従えば、継承関係のない入れ子クラス同士であっても相互のprivateフィールドアクセスが可能。
関連URL
*1:本記事では「リフレクション(reflection)」は考慮しない。なお、JavaセキュリティマネージャによってはsetAccessibleメソッド呼び出しを拒否する。
*2:公式The Java Tutorialsによれば、入れ子クラス(nested class)=static/非staticクラス、インナークラス(inner class)=非staticクラスを指す用語らしい。