开发者

Possible to change the outer class instance of an inner class in Java?

In Java, whenever an inner class instance is created, it is associated with an instance of an开发者_StackOverflow中文版 outer class. Out of curiosity, is it possible to associate the inner class with another instance of an outer class instead?


Yes, this is possible, although it sounds like a really bad idea to me. The idea is to set the otherwise final pointer to the outer instance using reflection (which is not guaranteed to succeed).

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!"
    }

}

The crucial part here is outerThis.setAccessible(true); -- a SecurityManager could enforce a policy that prohibits this from succeeding.


If you are speaking about instantiation time, it's possible using the following syntax:

public class Outer {
    public class Inner {}
}
...
Outer o = new Outer();
Outer.Inner i = o.new Inner();

However, it's not possible (without setAccessible(true)) to associate the existing instance of inner class with the other instance of outer class, because the field pointing to the enclosing instance is final:

javap Outer$Inner

Compiled from "Outer.java"
public class Outer$Inner extends java.lang.Object{
    final Outer this$0;
    public Outer$Inner(Outer);
}


You should be able to, using reflection.

Just get all fields of the inner class (getClass().getDeclaredFields())and see which field holds the parent, then change it (using field.set(innerInstance, newParent). Before that you should make the field accessible - setAccessible(true))

Since the field appears to be final, you may take a look at this article to see how to circumvent that.

That said, you shouldn't need to do this at all - it would be a double ugly hack for no actual gain.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜