web-dev-qa-db-ja.com

すべての内部クラスがそれを囲むインスタンスを必要とするというのは本当ですか?

内部クラスという用語は、通常、「包含インスタンスを必要とするネストされたクラス」を意味すると解釈されます。ただし、JLSは次のように述べています。

8.1.3。内部クラスとそれを囲むインスタンス

[...]

内部クラスには、ローカル(§14.3)、匿名(§15.9.5)、および非静的メンバークラス(§8.5)が含まれます。

[...]

宣言が静的コンテキストで発生する内部クラスのインスタンスには、字句的に囲むインスタンスがありません。

また、

15.9.5。匿名クラス宣言

[...]

匿名クラスは常に内部クラスです(§8.1.3)。 static(§8.1.1、§8.5.1)になることはありません。

そして、匿名クラスが静的コンテキストで宣言される可能性があることはよく知られています。

_class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}
_

それを痛烈に説明するために、

new A() {}は、静的コンテキストで定義された、インスタンスを含まないネストされたクラスですが、静的なネストされたクラスではなく、内部クラスです。

私たちは皆、日常の使用においてこれらの用語に不適切な意味を割り当てていますか?

関連する興味のあるポイントとして、 この履歴仕様書 は用語トップレベルinner

staticクラスメンバーであるクラスとパッケージメンバーであるクラスは、どちらもトップレベルクラスと呼ばれます。これらは、最上位クラスがそれ自体のインスタンス変数のみを直接使用できるという点で内部クラスとは異なります。

一方、一般的な使用法では、トップレベルネストされたの反対であると見なされます。

33
Marko Topolnik

質問に示されている違いは、仕様の観点からは完全に理にかなっています。

  • 内部クラスには制限が適用されますが、これはインスタンスを囲む問題とは関係ありません(たとえば、静的メンバーがない場合があります)。

  • 静的にネストされたクラスの概念は、基本的に名前空間に関するものです。これらのクラスは、私たちが通常トップレベルのクラスと見なしているものとともに、当然のことながらトップレベルと呼ばれることがあります。

ネストされたクラス宣言からstaticを削除すると、2つの別々のことが同時に実行されます。

  1. クラスにそれを囲むインスタンスが必要になります。
  2. クラスをinnerにします。

innerを制限を伴うものと考えることはめったにありません。 インスタンスを囲むの懸念にのみ焦点を当てます。これははるかに目立ちます。ただし、仕様の観点からは、制限は重大な懸念事項です。

欠落しているのは囲んでいるインスタンスを必要とするクラスの用語です。 JLSで定義されているそのような用語はないため、関連するが実際には本質的に異なる用語をハイジャックしました(気づいていないようです)。

6
Marko Topolnik

さて、あなたの場合も匿名クラスにはそれを囲むインスタンスがありませんか?静的なのは参照であり、匿名クラスのインスタンスではありません。考えてみましょう:

class A {
   int t() { return 1; }
   static A a = new A() { { System.out.println(t()); } };
}
0
MrBackend