class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
OuterClass.InnerClass.i
を使用して静的フィールドにアクセスすることはできませんが、静的なものを記録する場合は、作成されたInnerClassオブジェクトの数は、そのフィールドを静的にするのに役立ちます。 なぜはJava内部クラスの静的フィールド/メソッドを禁止しますか?
編集:私はコンパイラを静的なネストされたクラス(または静的な内部クラス)で満足させる方法を知っていますが、私が知りたいのはJava内部クラス(または通常の誰かがそれについてもっと知っているなら、言語設計と実装の両方の側面からの内部クラス)。
内部クラスの背後にある考え方は、囲んでいるインスタンスのコンテキストで動作することです。どういうわけか、静的変数と静的メソッドを許可することは、この動機と矛盾しますか?
8.1.2内部クラスと包含インスタンス
内部クラスは、明示的または暗黙的に静的に宣言されていないネストされたクラスです。内部クラスは、静的初期化子(8.7)またはメンバーインターフェイスを宣言できません。内部クラスは、コンパイル時の定数フィールド(§15.28)でない限り、静的メンバーを宣言できません。
私が知りたいのは、なぜJava内部クラス内の静的フィールド/メソッドを禁止する
これらの内部クラスは「インスタンス」内部クラスだからです。つまり、それらは囲んでいるオブジェクトのインスタンス属性のようなものです。
それらは「インスタンス」クラスであるため、static
機能を許可することは意味がありません。なぜなら、static
はそもそもインスタンスなしで動作することを意図しているからです。
静的/インスタンス属性を同時に作成しようとするようなものです。
次の例をご覧ください。
class Employee {
public String name;
}
従業員の2つのインスタンスを作成する場合:
Employee a = new Employee();
a.name = "Oscar";
Employee b = new Employee();
b.name = "jcyang";
それぞれがプロパティname
に独自の値を持っている理由は明らかですよね?
同じことが内部クラスでも起こります。各内部クラスインスタンスは、他の内部クラスインスタンスから独立しています。
したがって、counter
クラス属性を作成しようとすると、2つの異なるインスタンス間でその値を共有する方法はありません。
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
上記の例でa
とb
のインスタンスを作成するとき、静的変数count
の正しい値は何ですか? InnerData
クラスの存在は、囲んでいるオブジェクトのそれぞれに完全に依存するため、それを判別することはできません。
そのため、クラスがstatic
として宣言されている場合、それ自体を生きるために生きているインスタンスはもう必要ありません。依存関係がないため、静的属性を自由に宣言できます。
これは反復的に聞こえると思いますが、インスタンス属性とクラス属性の違いを考えると、意味があります。
InnerClass
は(static
の)インスタンスに属するため、OuterClass
メンバーを持つことはできません。 InnerClass
をstatic
として宣言してインスタンスからデタッチすると、コードがコンパイルされます。
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
ところで:あなたはまだInnerClass
のインスタンスを作成することができます。このコンテキストでstatic
を使用すると、OuterClass
のインスタンスを囲むことなくそれを実行できます。
実際、静的フィールドが定数であり、コンパイル時に記述されている場合、静的フィールドを宣言できます。
class OuterClass {
void foo() {
class Inner{
static final int a = 5; // fine
static final String s = "hello"; // fine
static final Object o = new Object(); // compile error, because cannot be written during compilation
}
}
}
この「制限」に最も適していると思う動機は次のとおりです。内部クラスの静的フィールドの動作を外部オブジェクトのインスタンスフィールドとして実装できます。 だから不要静的フィールド/メソッド。つまり、あるオブジェクトのすべての内部クラスインスタンスがフィールド(またはメソッド)を共有するという動作です。
したがって、すべての内部クラスインスタンスをカウントする場合は、次のようにします。
public class Outer{
int nofInner; //this will count the inner class
//instances of this (Outer)object
//(you know, they "belong" to an object)
static int totalNofInner; //this will count all
//inner class instances of all Outer objects
class Inner {
public Inner(){
nofInner++;
totalNofInner++;
}
}
}
内部クラスは囲む/外部クラスのインスタンスに依存するため、外部クラスは内部クラスの初期化の前に初期化する必要があります。
これはJLSがクラスの初期化について述べている 必要なポイントは、クラスTが初期化される場合です。
- Tによって宣言された静的フィールドが使用され、フィールドは定数変数ではありません。
したがって、内部クラスに静的フィールドへのアクセスがある場合、内部フィールドの初期化が行われますが、それにより、囲むクラスが初期化されることは保証されません。
基本的なルールに違反する。 最後のセクションにスキップして(two cases
に)noobを避けることができます
static nested
class
についての1つのこと、一部のnested class
がstatic
の場合、通常のように動作しますクラスはあらゆる方法で、Outerクラスに関連付けられています。
しかし、Inner class
/non-static
nested class
の概念は、outer /のinstance
に関連付けられますエンクロージングクラス。クラスではなくinstanceに関連付けられていることに注意してください。インスタンスとの関連付けは、(インスタンス変数の概念から)インスタンス内に存在し、インスタンス間で異なることを明確に意味します。
現在、静的なものを作成する場合、クラスがロードされているときに初期化され、すべてのインスタンス間で共有される必要があります。しかし、非静的であるため、内部クラス自体(現時点では内部クラスのインスタンスを忘れることができます)は、外部/囲みクラスのすべてのインスタンス(少なくとも概念的に)、その後、内部クラスの変数が内部クラスのすべてのインスタンス間で共有されることをどのように期待できますか?.
したがって、Javaネストされた静的クラスではなく、内部で静的変数を使用できます。2つのケースがあります。
context of instance
(インスタンス変数)の概念に違反します。それはNOです。簡単に言えば、非静的内部クラスは外部クラスのインスタンス変数であり、外部クラスが作成され、実行時に外部クラスオブジェクトが作成され、静的変数がクラスのロード時に作成される場合にのみ作成されます。したがって、非静的内部クラスは実行時のものであるため、静的ではない内部クラスの一部ではありません。
注:内側のクラスは常に外側のクラスの変数のように扱い、他の変数のように静的または非静的にすることができます。