Possible to change the outer class instance of an

2020-08-22 04:38发布

In Java, whenever an inner class instance is created, it is associated with an instance of an outer class. Out of curiosity, is it possible to associate the inner class with another instance of an outer class instead?

标签: java
3条回答
The star\"
2楼-- · 2020-08-22 05:07

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.

查看更多
姐就是有狂的资本
3楼-- · 2020-08-22 05:18

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.

查看更多
▲ chillily
4楼-- · 2020-08-22 05:24

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);
}
查看更多
登录 后发表回答