Java 反射在访问它时返回两个构造函数';来自内部类的私有构造函数

Java 反射在访问它时返回两个构造函数';来自内部类的私有构造函数,java,reflection,Java,Reflection,在上面的示例中,基类中有一个无参数构造函数。现在我列出这个类的构造函数,如下所示: public class Base { private Base instance; private Base() { } public static class BaseHelper { Base instance = new Base(); } } 这告诉我有两个构造函数: 我声明的私有构造函数 公共默认构造函数 这是为什么?编译器创建了两个

在上面的示例中,基类中有一个无参数构造函数。现在我列出这个类的构造函数,如下所示:

public class Base {

    private Base instance;

    private Base() {
    }

    public static class BaseHelper {
        Base instance = new Base();
    }
}
这告诉我有两个构造函数:

  • 我声明的私有构造函数
  • 公共默认构造函数

这是为什么?

编译器创建了两个构造函数,因为
BaseHelper
类访问
Base
类的私有构造函数

编译时,内部类从包含类中“提取”。如果类
BaseHelper
Base
类之外,则它无法访问私有构造函数-这就是编译器创建合成构造函数的原因。这是您看到的第二个构造函数

本质上是指编译器生成的

[private com.Base(), com.Base(com.Base)]

你能解释一下“但是当我使用反射API时,我可以看到两个构造函数”是什么意思吗?哪两个构造函数?一旦格式被修复,这是一个好问题。我们应该考虑一个更好的标题,这样有类似问题的人可以更容易地找到它…我同意。为什么这个问题有4张反对票?这是我多年来看到的最好的问题之一。我不相信投票人知道答案。感谢Max的回答,我还有一个疑问,为什么它要创建带参数的构造函数(正如我在问题中提到的)。我找不到任何可靠的来源,但我猜构造函数需要一个
Base
类型的对象,以避免其他代码无法通过反射调用此构造函数。它不是Base,而是Base$1。它看起来也创建了一个合成类。@pbabcdefp您在哪里看到它是
Base$1
?对于我来说,输出constructors参数的类名会给出一个
de.test.Base
。他们显然决定将其更改为Java8。我认为maxdev关于需要一个Base(阻止您通过反射调用这个构造函数)的解释是非常合理的。然而,漏洞在于Base可能会有另一个公共构造函数使用字符串,比如。在这种情况下,如果BaseHelper调用私有的no args构造函数,那么仍然需要合成构造函数,并且您可以通过传递使用字符串构造的基来调用合成构造函数。创建一个合成类会使整个过程更加紧凑。
[private com.Base(), com.Base(com.Base)]
package de.test;

import java.lang.reflect.Constructor;

public class Base {

    private Base instance;

    private Base() {
    }

    public static class BaseHelper {
        Base instance = new Base();
    }

    public static void main(String[] args) {
        Constructor[] constructors = Base.class.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor + " - synthetic? " + constructor.isSynthetic());
        }
    }
}