기술적으로 가능합니다.
실제로 이것은 일종의 해킹이므로 프로덕션 코드에서 이러한 연습을 피해야합니다.
예 :
여기
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)
을 호출하여 클래스의 인스턴스를 생성하는 것은 생성자에 매개 변수로 전달됩니다. 생성자 매개 변수에 대해서는 위의 설명을 참조하십시오.
마지막으로, 우리는 단지 암시 적 방법의 범위를 정확하게하는 방법을 제한하는 내부 클래스를 정의하는 InnerClass::toString()
유일한 이유를 호출 객체를 만들어 인쇄 할 수 있습니다. 다른 위치에서 액세스하려면 더 높은 범위에서 정의하십시오. –
현재 자바 코드로 작동하는 도구를 개발 중입니다. 그래서 도구가 자동으로 내부 클래스의 위치를 변경하면 코드의 핵심을 깨뜨릴 수 있는지 알아야합니다. –
그리고 개발자로서 어떻게 할 수 있는지 이해해야합니다. 감사합니다 user882813 나는 방법을 안다. –