传入匿名内部类时的空对象

Way*_*man 2 java inner-classes java1.4

传递最终对象时(下面代码中的一个String),当从匿名内部类打印时,它显示为null.但是,当传入最终值类型或直接最终字符串时,将正确显示其值.final在匿名内部类的上下文中真正意味着什么,为什么对象传递为null?

public class WeirdInners
{
    public class InnerThing
    {
        public InnerThing()
        {
            print();
        }

        public void print(){

        }
    }

    public WeirdInners()
    {
        final String aString = "argh!".toString();
        final String bString = "argh!";
        System.out.println(aString);
        System.out.println(bString);


        InnerThing inner =new InnerThing(){
            public void print()
            {
                System.out.println("inner"+aString); // When called from constructor, this value is null.
                System.out.println("inner"+bString); // This value is correctly printed.
            }
        };

        inner.print();
    }


    public static void main(String[] args)
    {
        WeirdInners test1 = new WeirdInners();
    }

}
Run Code Online (Sandbox Code Playgroud)

这对我来说是非常奇怪的行为,因为期望String 一个对象,为什么调用会toString()改变一些东西?

其他信息:仅使用Java 1.4,而不是Java 5中观察到此行为.有关解决方法的任何建议吗?不调用toString()现有的String是公平的,但由于这只是一个例子,如果我在非String对象上执行它会产生现实世界的影响.

Tom*_*ine 5

如果你查看compile-time constantsJLS中的部分,你会发现调用.toString()确实有所作为.和胡说八道一样false?null+"":.

这里重要的是设置关闭的字段和构造函数的相对顺序.如果你使用-target 1.4或以后(这不是1.4中的默认值!)那么在调用super之前将复制字段.使用1.3之前的规范,这是非法的字节码.

在这些情况下通常就是这种情况,javap -c看看javac编译器正在做什么很有用.该规范有助于理解为什么(如果你有足够的耐心).