내부 클래스 개체에서 외부 클래스 개체를 가져오는 중
나는 다음과 같은 코드를 가지고 있습니다.내부 클래스 개체를 만든 외부 클래스 개체를 가져오고 싶다.inner어떻게 해야 하죠?
public class OuterClass {
public class InnerClass {
private String name = "Peakit";
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
InnerClass inner = outer.new InnerClass();
// How to get the same outer object which created the inner object back?
OuterClass anotherOuter = ?? ;
if(anotherOuter == outer) {
System.out.println("Was able to reach out to the outer object via inner !!");
} else {
System.out.println("No luck :-( ");
}
}
}
편집: 일부에서는 메서드를 추가하여 내부 클래스를 수정할 것을 제안했습니다.
public OuterClass outer() {
return OuterClass.this;
}
그러나 내부 클래스를 수정할 수 없는 경우 내부 클래스 개체에서 해당 외부 클래스 개체를 가져올 수 있는 다른 방법이 있습니까?
내부 클래스 자체 내에서 다음을 사용할 수 있습니다.OuterClass.this이 표현은 어휘적으로 둘러싸인 인스턴스를 참조할 수 있으며 JLS에서는 Qualified로 기술되어 있습니다.
내부 계급의 코드 외부에서 인스턴스를 가져올 방법은 없다고 생각합니다.물론 언제든지 자신의 자산을 소개할 수 있습니다.
public OuterClass getOuter() {
return OuterClass.this;
}
EDIT: 실험 결과 외부 클래스에 대한 참조를 유지하는 필드에는 패키지 수준의 액세스 권한이 있는 것 같습니다(적어도 사용 중인 JDK).
EDIT: 사용된 이름(this$0JLS에서는 사용을 권장하지 않지만 실제로는 Java에서 유효합니다.
그
$문자는 기계적으로 생성된 소스 코드 또는 드물게 레거시 시스템의 기존 이름에 액세스할 때만 사용해야 합니다.
OuterClass.this는 외부 클래스를 참조합니다.
업무에 반영을 사용할 수 있습니다(사용해서는 안 됩니다).
import java.lang.reflect.Field;
public class Outer {
public class Inner {
}
public static void main(String[] args) throws Exception {
// Create the inner instance
Inner inner = new Outer().new Inner();
// Get the implicit reference from the inner to the outer instance
// ... make it accessible, as it has default visibility
Field field = Inner.class.getDeclaredField("this$0");
field.setAccessible(true);
// Dereference and cast it
Outer outer = (Outer) field.get(inner);
System.out.println(outer);
}
}
물론, 암묵적인 참조의 이름은 전혀 신뢰할 수 없기 때문에, 말씀드렸듯이, 다음과 같이 해서는 안 됩니다.
이 질문에 대한 보다 일반적인 답변은 음영 변수와 이러한 변수에 액세스하는 방법에 관한 것입니다.
다음 예에서는 (Oracle에서) 변수 x in main()이 섀도우링 테스트입니다.x:
class Test {
static int x = 1;
public static void main(String[] args) {
InnerClass innerClassInstance = new InnerClass()
{
public void printX()
{
System.out.print("x=" + x);
System.out.println(", Test.this.x=" + Test.this.x);
}
}
innerClassInstance.printX();
}
public abstract static class InnerClass
{
int x = 0;
public InnerClass() { }
public abstract void printX();
}
}
이 프로그램을 실행하면 다음과 같이 인쇄됩니다.
x=0, Test.this.x=1
자세한 것은, http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6 를 참조해 주세요.
다음은 예를 제시하겠습니다.
// Test
public void foo() {
C c = new C();
A s;
s = ((A.B)c).get();
System.out.println(s.getR());
}
// classes
class C {}
class A {
public class B extends C{
A get() {return A.this;}
}
public String getR() {
return "This is string";
}
}
내부 클래스를 수정할 수 있는 제어 권한이 없는 경우, 리페션이 도움이 될 수 있습니다(권장되지는 않음).이 $0은 Inner 클래스의 현재 인스턴스를 만들기 위해 사용된 Outer 클래스의 인스턴스를 나타내는 Inner 클래스의 참조입니다.
/**
* Not applicable to Static Inner Class (nested class)
*/
public static Object getDeclaringTopLevelClassObject(Object object) {
if (object == null) {
return null;
}
Class cls = object.getClass();
if (cls == null) {
return object;
}
Class outerCls = cls.getEnclosingClass();
if (outerCls == null) {
// this is top-level class
return object;
}
// get outer class object
Object outerObj = null;
try {
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
if (field != null && field.getType() == outerCls
&& field.getName() != null && field.getName().startsWith("this$")) {
field.setAccessible(true);
outerObj = field.get(object);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return getDeclaringTopLevelClassObject(outerObj);
}
물론 암묵적 참조의 이름은 신뢰할 수 없으므로 작업에 반영을 사용해서는 안 됩니다.
언급URL : https://stackoverflow.com/questions/1816458/getting-hold-of-the-outer-class-object-from-the-inner-class-object
'source' 카테고리의 다른 글
| Vuex-persist가 localStorage에 아무것도 저장하지 않는 이유는 무엇입니까? (0) | 2022.08.25 |
|---|---|
| Null Pointer를 명시적으로 슬로우하는 이유자연스럽게 일어나는 것이 아니라 예외인가? (0) | 2022.08.25 |
| Larabel 5.5 및 Vue.js 블레이드 테스트 (0) | 2022.08.25 |
| 왜 this()와 super()가 컨스트럭터의 첫 번째 문이어야 합니까? (0) | 2022.08.25 |
| 기억과 관련하여 아레나라는 용어의 의미는 무엇입니까? (0) | 2022.08.25 |