技術的に可能です。
これは実際にはハックのようなもので、プロダクションコードでこのような習慣を避けるべきです。
例:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Example {
public void outerMethod() {
class InnerClass {
private double d = 7.62;
@Override
public String toString() {
return String.format("[%s] d = %f", this.getClass().getName(), d);
}
}
}
public void testMethod() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
final Class<?> clazz = Class.forName("Example$1InnerClass");
final Constructor<?> constructor = clazz.getDeclaredConstructor(Example.class);
constructor.setAccessible(true);
final Object instance = constructor.newInstance(this);
System.out.println(instance);
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Example instance = new Example();
instance.testMethod();
}
}
ここでは、最初に自分の名前で私たちの地域のクラスのClass<?>
を取得します。
ローカルクラス名生成規則は、コンパイラの実装の詳細であり、変更される可能性があります。 AFAIK javac
およびECJ
は異なるアプローチを使用します。
次に、リフレクションによって興味のあるクラスのコンストラクタを取得します。
クラスはコンストラクタを明示的に定義していないため、コンパイラは自動的に生成します。このコンストラクタはpublicではありません。ここではgetDeclaredConstructor()
メソッドを使用します。
このクラスは静的ではないため(ローカルクラスは静的に定義できません)、コンストラクタの最初と唯一のパラメータは外部クラス参照です。我々の場合はExample
です。
その後、constructor.newInstance(this)
this
を呼び出してクラスのインスタンスを作成し、コンストラクタに渡します。コンストラクタパラメータについては上記の注を参照してください。
は最後に、我々は、暗黙的にメソッド内でクラスを定義するための唯一の理由は正確にそのメソッドにその範囲を制限することですInnerClass::toString()
を呼び出すだけで作成したオブジェクトを印刷します。他の場所からアクセスする場合は、より高いスコープで定義します。 –
私は現在、Javaコードで動作するツールを開発中です。だから私はツールが自動的に内部クラスの場所を変更するかどうかは、コードのcorectnessを破ることができるかどうかを知る必要があります。 –
そして、開発者として私はそれがどのようにできるかを理解する必要があります。 user882813に感謝します。 –