为什么classname $ 1.class会在这种情况下生成?

我编写了以下代码来实现Singleton模式:

public final class Test { static final class TestHolder { private static final Test INSTANCE = new Test(); } private Test() {} public static Test getInstance() { return TestHolder.INSTANCE; } } 

当我编译这个文件时,它应该生成Test.class和Test $ TestHolder.class,但它也会生成Test $ 1.class。 这没有意义。 那么为什么以及如何呢?

TestHolder类需要在Test调用私有构造函数。 但它是私有的,实际上不能从另一个类调用。 所以编译器起了作用。 它Test添加了一个新的非私有构造函数,只有它知道! 该构造函数接受此匿名类Test$1的(未使用的)实例 – 没有人知道存在。 然后TestHolder创建一个Test$1的实例并调用构造函数,该构造函数是可访问的(它是默认保护的。)

您可以使用javap -c Test (以及javap -c Test\$1javap -c Test\$TestHolder )来查看代码。 实际上它非常聪明!