Java 单例程序中静态语句的使用和流程

Java 单例程序中静态语句的使用和流程,java,static,singleton,Java,Static,Singleton,我知道有很多关于单身模式的问题。但这里我想知道的是关于输出的内容,可能还包括“静态”在Java中的工作方式 public class Singleton { private static Singleton currentSingleton = new Singleton(); public static Singleton getSingleton() { return currentSingleton; } private Singlet

我知道有很多关于单身模式的问题。但这里我想知道的是关于输出的内容,可能还包括“静态”在Java中的工作方式

public class Singleton {
    private static Singleton currentSingleton = new Singleton();

    public static Singleton getSingleton() { 
        return currentSingleton;
    }

    private Singleton() {
        System.out.println("Singleton private constructor...");
    }

    public static void main(String[] args) {
        System.out.println("Main method...");
    }
}

这是运行代码的输出

单例私有构造函数<主要方法

当我调试这段代码时,控件首先进入第行
System.out.println(“单例私有构造函数…”)
并打印。 (此时专用静态变量currentSingleton仍然为空)
然后转到第行
private static Singleton currentSingleton=new Singleton()
然后初始化私有变量。
最后,它转到main()方法并打印

我的问题是:

  • 为什么它首先打印私有构造函数中的“单例私有构造函数…”。 我认为控件应该首先转到main()方法,因为它是入口点。此外,我没有在任何地方创建任何实例(变量初始化除外)
  • 稍后它将转到静态变量实例化行(此时currentSingleton=null)
    private static Singleton currentSingleton=new Singleton()
    虽然currentSingleton在这里得到一个值,但为什么不再次调用构造函数呢

  • 我主要想知道这个程序的控制流程。

    在类中的main方法被正确初始化之前(即静态字段和静态块已被计算),您不能调用它。初始化时,通过调用私有构造函数创建singleton的实例。稍后调用main方法

    所讨论的类有一个静态字段,您可以向其赋值。由于该字段是静态的,因此必须先对其进行初始化,然后才能在任何上下文中使用该类,也就是说,它必须接收一个值。在这种情况下,它的值恰好是同一类的实例。这就是在类初始化期间触发私有构造函数的原因


    如果您想深入研究该过程并更好地理解它,请参阅。更具体地说,在第12.4节中,您将看到更多详细信息。

    每当控件第一次出现在任何类上时,所有静态初始化都首先发生。这就是为什么在调用静态对象的构造函数之前先实例化它。

    在控件访问main()方法之前,需要初始化该类。由于您使用声明内联初始化了
    currentSingleton
    ,因此在类加载期间,此初始化发生在main()之前。

    您应该将其声明为
    final

    private static final Singleton currentSingleton = new Singleton();
    
  • 初始化值为编译时常量的接口的最终类变量和字段
  • 回答你的两个问题

    如果声明符用于类变量(即静态字段),则在初始化类时,变量初始值设定项将被求值并执行一次赋值(§12.4.2)


    类首先由JVM的类加载器加载和初始化。JVM在初始化时扫描类(Singleton),并在初始化时初始化第一行中的静态变量。该变量调用构造函数并打印其中的行。初始化类后,它将调用main方法,从而打印其中的语句。

    由于必须初始化
    currentSingleton
    静态字段,因此
    new Singleton()
    语句是第一个执行的语句;这意味着为正在创建的单例对象分配内存,并在将结果对象分配给字段变量之前执行其构造函数。 这就是
    System.out.println(“单例私有构造函数…”)的原因分配前正在执行的行。
    
    此外,静态字段初始化会在类被引用时立即发生,调用Singleton类的main函数意味着引用它,这就是在main方法之前执行初始化的原因。

    为了澄清:
    ,直到它被正确初始化为止。
    ->
    这里是类对象,好的,第一个类应该正确初始化,所以它将调用行private static Singleton currentSingleton=new Singleton();然后它应该调用构造函数并打印语句。但当我调试它时,控件首先进入私有构造函数,打印,然后初始化私有静态变量。这就是我感到困惑的原因。@amit这个类有一个静态字段,您可以将一个值赋给它。由于该字段是静态的,因此必须使用类对其进行初始化,也就是说,它必须接收一个值。在这种情况下,它的值恰好是同一类的实例。这就是在类初始化期间触发私有构造函数的原因。是的,我看错了。我在
    it=class对象
    中的意思是:在调用
    main()
    之前,必须实例化class对象。(由此可以得到,为了让它发生,赋值
    currentSingleton=new Singleton();
    必须发生,这反过来又实例化了对象)。(顺便说一句,我已经给出了答案。)@amit你可能需要阅读更多细节。