例:
public class TestClass {
public static void main(String[] args) {
TestClass t = new TestClass();
}
private static void testMethod() {
abstract class TestMethod {
int a;
int b;
int c;
abstract void implementMe();
}
class DummyClass extends TestMethod {
void implementMe() {}
}
DummyClass dummy = new DummyClass();
}
}
上記のコードはJavaでは完全に合法であることがわかりました。以下の質問があります。
DummyClass
のクラスファイルが生成されますかこれはローカルクラスと呼ばれます。
2は簡単です。はい、クラスファイルが生成されます。
1と3は同じ質問です。ローカルクラスを使用するのは、1つのメソッド以外の場所でインスタンス化する必要も、実装の詳細を知る必要もない場合です。
典型的な用途は、何らかのインターフェースの使い捨て実装を作成することです。たとえば、次のようなものが頻繁に表示されます。
//within some method
taskExecutor.execute( new Runnable() {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
});
これらの束を作成してそれらを使用する必要がある場合は、これを
//within some method
class myFirstRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
}
class mySecondRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomethingElse( parameter );
}
}
taskExecutor.execute(new myFirstRunnableClass());
taskExecutor.execute(new mySecondRunnableClass());
インターフェースに関して:ローカル定義のインターフェースがコンパイラーにとって問題となる技術的な問題があるかどうかはわかりませんが、たとえ存在しなくても、付加価値はありません。ローカルインターフェイスを実装するローカルクラスがメソッドの外部で使用された場合、インターフェイスは無意味になります。また、ローカルクラスがメソッド内でのみ使用される場合、インターフェイスとクラスの両方がそのメソッド内で実装されるため、インターフェイス定義は冗長になります。
それらはローカルクラスと呼ばれます。詳細な説明と例があります here 。この例は、メソッドの外部について知る必要のない特定の実装を返します。
クラスは、メソッドの外部からは見えません(つまり、インスタンス化され、そのメソッドはReflectionなしでアクセスされます)。また、testMethod()で定義されたローカル変数にアクセスできますが、クラス定義の前にアクセスできます。
私は実際に考えました:「そのようなファイルは書かれません」。試してみるまで:そうそう、そのようなファイルが作成されます! A $ 1B.classのような名前になります。ここで、Aは外部クラス、Bはローカルクラスです。
特に、コールバック関数(ボタンがクリックされたときのonClick()などのGUIのイベントハンドラー)の場合、「匿名クラス」を使用することは非常に一般的です。ただし、匿名クラスでは不十分な場合があります。特に、コンストラクターを定義できない場合があります。これらの場合、これらのメソッドローカルクラスが適切な代替手段となります。
これの本当の目的は、関数呼び出しでクラスをインラインで作成し、関数型言語で書いているふりをしたい人を慰めることです;)
完全な関数内部クラスと匿名クラス(a.k.a. Java closure)を使用したい場合は、次の条件が満たされている場合のみです。
例えば。誰かがRunnable
を望んでいて、実行の開始と終了を記録したい場合。
匿名クラスでは実行できませんが、内部クラスではこれを実行できます。
ここに私のポイントを示す例があります
private static void testMethod (
final Object param1,
final Object param2
)
{
class RunnableWithStartAndEnd extends Runnable{
Date start;
Date end;
public void run () {
start = new Date( );
try
{
evalParam1( param1 );
evalParam2( param2 );
...
}
finally
{
end = new Date( );
}
}
}
final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );
final Thread thread = new Thread( runnable );
thread.start( );
thread.join( );
System.out.println( runnable.start );
System.out.println( runnable.end );
}
ただし、このパターンを使用する前に、単純な古いトップレベルクラス、内部クラス、または静的内部クラスがより良い代替手段であるかどうかを評価してください。
(メソッドまたはクラス内で)内部クラスを定義する主な理由は、メンバーと、それを囲むクラスとメソッドの変数のアクセシビリティに対処するためです。内部クラスは、プライベートデータメンバーを検索し、それらを操作できます。メソッド内であれば、最終ローカル変数も処理できます。
内部クラスを持つことは、このクラスが外部からアクセスできないようにするのに役立ちます。これは、JS生成コードがJavaで記述され、各ボタンまたはイベントの動作を匿名クラスを作成して定義する必要があるGWTやGXTなどのUIプログラミングの場合に特に当てはまります。