什么时候会将静态嵌套类(以及其中的静态成员)加载到内存中?

12

在这里,我正在尝试使用内部静态辅助类实现单例模式以便于连接数据库:

package com.myapp.modellayer;

public class DatabaseConnection {

    private DatabaseConnection() {
        //JDBC code...
    }

    private static class ConnectionHelper {
        // Instantiating the outer class
        private static final DatabaseConnection INSTANCE = new DatabaseConnection();
    }

    public static DatabaseConnection getInstance() {
        return ConnectionHelper.INSTANCE;
    }
}

然而,我有疑问:这个静态内部类ConnectionHelper何时被加载到JVM内存中:

是在DatabaseConnection类被加载时,还是在调用getInstance()方法时?


2
请注意,在static class中的“static”一词与Java中成员声明中的“static”一词所指含义并不相同。这仅仅意味着它是一个嵌套的非内部 - user2864740
@user2864740 顺便说一下,那里的答案和其他99.9%关于这个主题的答案一样错误。实际上有这样一种内部类没有封闭实例。(例如,请参见此处)。 - William F. Jameson
1
静态嵌套类并没有什么特别之处。它们的加载方式与非静态和/或非嵌套类相同。对于JVM来说,所有类都是相同的,它并不真正理解Java所理解的嵌套。 - Peter Lawrey
2个回答

11

类何时被加载只是实现细节,您想知道的是类何时被初始化。仅在首次需要该类时才会进行初始化,也就是调用getInstance()时。

顺便提一下,您正在使用基于Java语言规范确切保证的延迟初始化占位符模式。正如Josh Bloch所说:

这个模式几乎是神奇的。虽然有同步操作正在进行,但它是不可见的。Java Runtime Environment将在幕后为您执行此操作。许多虚拟机实际上会对代码进行修补,以消除不再必要的同步,因此这种模式非常快速。


我曾在某处读到过这个线程安全机制被广泛应用于单例设计模式中,但对类的加载不确定。 - Amitesh Rai

5

Oracle文档页面如下所述:

注意:静态嵌套类与其外部类(和其他类)的实例成员交互,就像任何其他顶级类一样。实际上,静态嵌套类在行为上是一个顶级类,它已经为了方便打包而嵌套在另一个顶级类中。

它的加载方式与其他类的加载方式相同。


这必须是问题的被接受答案,因为它准确地解释了用户所问的内容。被接受的答案甚至与问题无关。 - Rakesh Yadav
@RakeshYadav 是的,我同意。 - rupesh jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接