可以在Java中更改内部类的外部类实例吗?
在Java中,每当创建内部类实例时,它都与外部类的实例相关联。 出于好奇,是否可以将内部类与外部类的另一个实例相关联?
是的,这是可能的,虽然这对我来说听起来真是个糟糕的主意。 我们的想法是使用reflection设置指向外部实例的final
指针(不保证成功)。
import java.lang.reflect.*; public class Me { final String name; Me(String name) { this.name = name; } class InnerMe { String whoAreYou() { return name; } } InnerMe innerSelf() { return new InnerMe(); } public static void main(String args[]) throws Exception { final Me me = new Me("Just the old me!"); final InnerMe innerMe = me.innerSelf(); System.out.println(innerMe.whoAreYou()); // "Just the old me!" Field outerThis = innerMe.getClass().getDeclaredFields()[0]; outerThis.setAccessible(true); outerThis.set(innerMe, new Me("New and improved me!")); System.out.println(innerMe.whoAreYou()); // "New and improved me!" } }
这里的关键部分是outerThis.setAccessible(true);
– SecurityManager可以强制执行禁止成功的策略。
如果您正在谈论实例化时间,可以使用以下语法:
public class Outer { public class Inner {} } ... Outer o = new Outer(); Outer.Inner i = o.new Inner();
但是,不可能(没有setAccessible(true)
)将内部类的现有实例与外部类的另一个实例相关联,因为指向封闭实例的字段是final
:
javap Outer$Inner Compiled from "Outer.java" public class Outer$Inner extends java.lang.Object{ final Outer this$0; public Outer$Inner(Outer); }
你应该能够使用reflection。
只需获取内部类的所有字段( getClass().getDeclaredFields()
)并查看哪个字段包含父项,然后更改它(使用field.set(innerInstance, newParent)
。在此之前,您应该使该字段可访问 – setAccessible(true)
))
由于该字段似乎是final
,您可以查看本文以了解如何规避它。
也就是说,你根本不应该这样做 – 这将是一个双重丑陋的黑客,没有实际收益。