我有以下代码:

class Foo {
    static { //static initializer block
        System.out.print("Foo");
    }
    class Bar {
        static { //static initializer block
            System.out.print("Bar");
        }
    }

    public static void main(String[] args) { // => This will print "FooBar" to the console
        new Foo().new Bar();
    }
}

public class Main {

    public static void main(String[] args) { // This will print "BarFoo" to the console
        new Foo().new Bar();
    }
}

正如注释所说,它们将在独立调用Main方法时打印不同的结果.为什么在这种情况下Main方法的放置会影响打印到屏幕上的结果?

推荐答案

new Foo().new Bar()被编译为以下字节码:

NEW Foo$Bar
DUP
NEW Foo
DUP
INVOKESPECIAL Foo.<init> ()V
INVOKESPECIAL Foo$Bar.<init> (LFoo;)V

请注意,首先创建的是Bar(尽管首先调用的是Foo‘S构造函数).new指令导致类被初始化(参见spec),not是构造函数调用.当一个类被初始化时,它的静态初始化器运行(见spec).

如果您不知道,非静态内部类是通过让构造函数接受一个额外的参数来实现的,该参数用作封闭实例.new Foo().new Bar()基本上等于new Foo.Bar(new Foo()),但只有前一种语法才有效.

我不确定这样的输出是否符合规范中的行为guaranteed.从技术上讲,它的编译方式可以使NEW Foo首先出现,但这将需要一个额外的变量,就像您编写的那样:

var f = new Foo();
f.new Bar();

因此,当您将new Foo().new Bar()放入一个不相关的类中时,Bar首先被初始化,因此Bar首先被打印.

然而,当您将new Foo().new Bar()放入在Foo中声明的静态方法中时,Foo将在new条指令中的任何指令之前被初始化,因此Foo首先被打印.这是因为在Foo中调用静态方法会导致Foo被初始化.

请参阅spec中要初始化的类或接口T的所有条件:

  • T是一个类,并且创建了T的一个实例.

  • 调用由T声明的静态方法.

  • 由T声明的静态字段被赋值.

  • 使用由T声明的静态字段,并且该字段不是常量变量(§4.12.4).

请注意,第一个引用的是new指令的执行,而不是构造函数调用.

Java相关问答推荐

为什么JFrame paint()多次绘制同一点(或根本不绘制)?

Android视图覆盖不阻止点击它后面的控件

我想了解Java中的模块化.编译我的应用程序时,我有一个ResolutionException

使用Java Streams API比较两个不同的Java集合对象和一个公共属性

取消按钮,但没有任何操作方法引发和异常

Java List with all combinations of 8 booleans

将不受支持的时区UT重写为UTC是否节省?

是否在允许数组元素为空时阻止 idea 为空性警告?

在Spring终结点中,是否可以同时以大写和小写形式指定枚举常量?

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

我可以在MacOS上使用什么Java函数来在适当的设备上以适当的音量播放适当的alert 声音?

用OSQL创建索引

如何集成语义发布和BitBucket(Java项目)

如何在JavaFX中制作鼠标透明stage

JNI:将代码打包成自包含的二进制文件

与IntArray相比,ArrayList<;Int>;对于大量元素的性能极差

如果c不为null,Arrays.sort(T[]a,Comparator<;?super T>;c)是否会引发ClassCastException?

如何使用stream.allMatch()为空流返回false?

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序

Java中计算大n和k值模10^9+7的二项式系数的乘法公式输出错误值