在Java中是否可以更改内部类的外部类实例?

9
在Java中,每当创建一个内部类实例时,它都会与外部类的一个实例相关联。出于好奇,是否可以将内部类与另一个外部类实例关联起来呢?

除了在未来的混淆Java竞赛中可能具有潜力外,它还有什么意义呢?你知道如果你想要一个可以与其父类分离的内部类,你只需要声明它为静态的,对吧? - Steve B.
我觉得这个问题很有趣。有没有人知道在JLS中是怎么规定外部类指针的名字的?通过不断实验,我发现它似乎被命名为this$0,后面可能跟随多个$(也可能一个也没有)。这是否已经被明确规定了呢? - polygenelubricants
好的,我刚刚发现一个二级内部类使用this$1。真有趣! - polygenelubricants
@Steve:这个问题纯粹是出于好奇,我没有使用这个功能的意图。 - Casebash
@polygenelubricants - 据我所知,JLS没有指定这一点。这在理论上至少是JVM/编译器实现特定的。这也是为什么做这种事情是疯狂的另一个原因。 - Stephen C
3个回答

6

是的,这是可能的,尽管对我来说听起来像一个非常糟糕的主意。这个想法是使用反射将否则为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可能会强制执行禁止此操作的策略。


5
如果你在谈论实例化时间,可以使用以下语法:
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);
}

4

您可以使用反射来实现。

只需获取内部类的所有字段(getClass().getDeclaredFields()),并查看哪个字段保存了父级,然后更改它(使用field.set(innerInstance, newParent))。在此之前,您应该将字段设置为可访问状态-setAccessible(true))。

由于该字段似乎是final,您可以查看此文章以了解如何绕过它。

也就是说,您根本不需要这样做-这是一个双重丑陋的黑客行为,没有任何实际的收益。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接