191

外部クラスが内部クラスのプライベート インスタンス変数にアクセスできることを確認しました。これはどのように可能ですか?同じことを示すサンプル コードを次に示します。

class ABC{
    class XYZ{
        private int x=10;
    }

    public static void main(String... args){
        ABC.XYZ xx = new ABC().new XYZ();
        System.out.println("Hello :: "+xx.x); ///Why is this allowed??
    }
}

この動作が許可されているのはなぜですか?

4

10 に答える 10

83

内部クラスは、元の外部クラスに実際に属するいくつかの機能を明確に分離する方法にすぎません。これらは、次の2つの要件がある場合に使用することを目的としています。

  1. 外部クラスの機能の一部は、別のクラスに実装されている場合に最も明確になります。
  2. 別のクラスにありますが、機能は外部クラスの動作方法と非常に密接に関連しています。

これらの要件を考慮すると、内部クラスは外部クラスに完全にアクセスできます。それらは基本的に外部クラスのメンバーであるため、プライベートを含む外部クラスのメソッドと属性にアクセスできることは理にかなっています。

于 2009-11-26T05:52:13.077 に答える
64

内部クラスのプライベート メンバーを隠したい場合は、パブリック メンバーを使用してインターフェイスを定義し、このインターフェイスを実装する匿名の内部クラスを作成できます。以下の例:

class ABC{
    private interface MyInterface{
         void printInt();
    }

    private static MyInterface mMember = new MyInterface(){
        private int x=10;

        public void printInt(){
            System.out.println(String.valueOf(x));
        }
    };

    public static void main(String... args){
        System.out.println("Hello :: "+mMember.x); ///not allowed
        mMember.printInt(); // allowed
    }
}
于 2012-02-28T08:54:39.557 に答える
59

内部クラスは、(アクセス制御の目的で) 包含クラスの一部と見なされます。これは、すべてのプライベートへのフル アクセスを意味します。

これを実装する方法は、合成パッケージ保護メソッドを使用することです。内部クラスは、同じパッケージ (ABC$XYZ) 内の別のクラスにコンパイルされます。JVM はこのレベルの分離を直接サポートしていないため、バイトコード レベルでは、ABC$XYZ は、外部クラスがプライベート メソッド/フィールドにアクセスするために使用するパッケージ保護されたメソッドを持ちます。

于 2009-11-26T06:01:18.360 に答える
20

これに似た別の質問に正しい答えが表示されます: 入れ子になったクラスのプライベート メンバーは、囲んでいるクラスのメソッドによってアクセスできるのはなぜですか?

JLS - Determining Accessibilityにプライベート スコープの定義があると書かれています。

それ以外の場合、メンバーまたはコンストラクターがプライベートであると宣言されている場合、メンバーまたはコンストラクターの宣言を囲む最上位クラス (§7.6) の本体内で発生した場合にのみ、アクセスが許可されます。

于 2014-03-28T03:06:02.910 に答える
8

Thiloは、最初の質問「これはどのように可能ですか?」に対する適切な回答を追加しました。2 番目に尋ねられた質問について少し詳しく説明したいと思います。なぜこの動作が許可されているのですか?

手始めに、この動作が内部クラスに限定されないことを完全に明確にしましょう。内部クラスは、定義上、静的ではないネストされた型です。この動作は、ネストされた列挙型と、静的である必要があり、外側のインスタンスを持つことができないインターフェイスを含む、すべてのネストされた型に対して許可されます。基本的に、モデルは次のステートメントに至るまで単純化されています。ネストされたコードは、囲んでいるコードに完全にアクセスできます。

では、なぜですか?例がポイントをよりよく説明していると思います。

あなたの体と脳について考えてみてください。ヘロインを腕に注射すると、脳がハイになります。あなたの脳の扁桃体領域が、彼があなたの身の安全に対する脅威であると信じているものを見つけた場合、たとえばハチを例に挙げると、彼はあなたの体を逆向きにさせ、あなたがそれについて二度「考える」ことなく、丘に向かって走らせます.

つまり、脳は身体の本質的な部分であり、奇妙なことに、その逆もあるのです。このような密接に関連するエンティティ間でアクセス制御を使用すると、関係の主張が失われます。アクセス制御が必要な場合は、クラスをさらに個別のユニットに分割する必要があります。それまでは同じユニットです。Iteratorさらなる研究の原動力となる例は、Javaが通常どのように実装されているかを調べることです。

囲んでいるコードから入れ子になったコードへの無制限のアクセスにより、ほとんどの場合、入れ子になった型のフィールドやメソッドにアクセス修飾子を追加しても役に立たなくなります。そうすることで混乱が増し、Java プログラミング言語の初心者に誤った安心感を与える可能性があります。

于 2014-08-08T11:30:06.640 に答える
5

内部クラスの重要な使用例は、ファクトリ パターンです。囲んでいるクラスは、アクセス制限なしで内部クラスのインスタンスを準備し、そのインスタンスを外部の世界に渡すことができます。外部の世界では、プライベート アクセスが受け入れられます。

abyxとは対照的に、クラス static を宣言しても、以下に示すように、外側のクラスへのアクセス制限は変更されません。また、同じエンクロージング クラス内の静的クラス間のアクセス制限も機能しています。私はびっくりしました ...

class MyPrivates {
    static class Inner1 { private int test1 = 2; }
    static class Inner2 { private int test2 = new Inner1().test1; }

    public static void main(String[] args) {
        System.out.println("Inner : "+new Inner2().test2);
    }
}
于 2011-11-08T23:18:34.153 に答える
3

アクセス制限は、クラスごとに行われます。クラスで宣言されたメソッドがすべてのインスタンス/クラス メンバーにアクセスできないことはありません。これは、内部クラスも外部クラスのメンバーに自由にアクセスでき、外部クラスが内部クラスのメンバーに自由にアクセスできるのは当然のことです。

クラスを別のクラス内に配置することにより、実装に密接に結び付けられ、実装の一部であるすべてのものは他の部分にアクセスできる必要があります。

于 2009-11-26T06:27:39.400 に答える
3

内部クラスの背後にあるロジックは、外部クラスに内部クラスを作成する場合、それはいくつかのものを共有する必要があるためであり、したがって、「通常の」クラスよりも柔軟性を持たせることが理にかなっています。

あなたの場合、クラスが互いの内部動作を確認できることが意味をなさない場合 - 基本的に、内部クラスを単に通常のクラスにすることができた可能性があることを意味し、内部クラスを として宣言できますstatic class XYZ。を使用staticすると、それらが状態を共有しないことを意味します (そして、たとえば、機能しnew ABC().new XYZ()ないため、 を使用する必要がありますnew ABC.XYZ()
しかし、その場合は、XYZ本当に内部クラスであるべきかどうか、おそらくそれ自体に値するかどうかを検討する必要があります。ファイル. 場合によっては、静的な内部クラスを作成することが理にかなっています (たとえば、外部クラスが使用しているインターフェイスを実装する小さなクラスが必要な場合、それは他の場所では役に立ちません)。外部クラスにするべきでした。

于 2009-11-26T06:42:18.140 に答える
-2

main()メソッドがABCクラス内にあるため、独自の内部クラスにアクセスできます。

于 2009-11-26T05:49:26.017 に答える