当前位置: 首页 > 面试题库 >

通过枚举方式的单例是否被延迟初始化?

靳金鹏
2023-03-14
问题内容

这是一个非常广泛的枚举单例代码:

public enum enumClazz{
   INSTANCE
   enumClazz(){
     //do something
   }
}

一堆地方说这是一个懒惰的初始化。但我很困惑我“读的第7章后,里面的Java虚拟机
” -一个类型的生命周期

Java虚拟机规范在类和接口加载和链接的时间上为实现提供了灵活性,但严格定义了初始化的时间。所有实现都必须在首次使用时初始化每个类或接口。以下六种情况可作为有效使用:

  • 将创建一个类的新实例(以字节码表示,一条新指令的执行。或者,通过隐式创建,反射,克隆或反序列化。)
  • 由类声明的静态方法的调用(以字节码表示,invokestatic指令的执行)
    * 类或接口声明的静态字段的使用或分配,但最终的静态字段由编译时常量表达式初始化(​​由字节码表示,执行getstatic或putstatic指令除外)
  • Java API中某些反射方法的调用,例如Class类中的方法或java.lang.reflect包中的类中的方法
  • 类的子类的初始化(类的初始化需要其超类的事先初始化。)
  • Java虚拟机启动时,将类指定为初始类(使用main()<方法)

第三点用粗体表示,如果该字段为static final,则该字段的初始化在编译时进行。同样,INSTANCEin
enumClazz隐式等于public static final并遵守第三点。

如果我的理解是错误的,有人可以纠正我吗?


问题答案:

enum实例字段 不是
“由编译时常量表达式初始化”。不能这样,因为对于编译时常量表达式,只有String和基本类型是可能的类型。

这意味着该类将在INSTANCE首次访问时进行初始化(这正是所需的效果)。

上面的粗体文本存在一个例外,因为这些常量(static final使用编译时常量表达式初始化的字段)将在编译期间有效地内联:

class A {
  public static final String FOO = "foo";

  static {
    System.out.println("initializing A");
  }
}

class B {
  public static void main(String[] args) {
    System.out.println(A.FOO);
  }
}

B在此示例中,执行类将 不会 初始化A(并且 不会显示
“正在初始化A”)。并且,如果您查看为之生成的字节码,B您会看到一个字符串文字,其值为“ foo”,并且 没有 对该类的引用A



 类似资料:
  • 很多地方都说这是一个懒惰的初始化。但是,当我阅读了“在Java虚拟机内部”的第7章--类型的生存期后,我感到困惑: Java虚拟机规范在类和接口加载和链接的时间上给了实现灵活性,但严格定义了初始化的时间。所有实现都必须在每个类或接口的第一次活动使用时对其进行初始化。以下六种情况属于有效用途: 创建一个类的新实例(在字节码中,新指令的执行。或者,通过隐式创建、反射、克隆或反序列化。) 类声明的静态方

  • 问题内容: 如果我有一堆枚举类型的枚举实例,并且如果我第一次访问它的一个实例,那么所有剩余的实例也会同时初始化。仅在第一次访问枚举实例时,有什么方法可以初始化它吗? 问题答案: 并非没有,基本上也就没有了。枚举是类。第一次使用类时,该类将由JVM加载并完成其所有静态初始化。设置枚举成员是静态初始化,因此它们都将被初始化。

  • 根据JavaEE 6教程: EJB容器负责确定何时初始化单例会话bean实例,除非单例会话bean实现类用javax注释。ejb。启动注释。在这种情况下,有时称为急切初始化,EJB容器必须在应用程序启动时初始化单例会话bean。在EJB容器向应用程序中的任何企业bean发送客户端请求之前,初始化单例会话bean。 Thorntail提供的RESTEasy应用程序不使用任何EJB,但它使用@Star

  • 7.4.4 延迟初始化的bean 默认情况下,ApplicationContext实现在初始化过程中随即创建和配置所有单例bean。一般来说,这种预实例化是可取的,因为可以立即发现配置或周围环境中的错误,而不是在几个小时甚至几天以后。当这种行为不可取时,可以通过将bean定义标记为延迟初始化来阻止预实例化。延迟初始化的bean告诉IoC容器,当bean首次被请求时而不是在启动时创建一个实例。 在X

  • 问题内容: 我需要延迟初始化地图及其内容。到目前为止,我有以下代码: 这显然不是线程安全的,就好像一个线程在null时出现,继续将字段初始化为,并且当该字段仍将数据加载到映射中时,另一个线程执行a 并且在可能存在的情况下不获取数据。 当第一次调用发生时,如何确保数据仅在地图中加载一次。 请注意,所有初始化后,地图中可能不会存在。同样,在所有初始化之后,映射可能只是空的。 问题答案: 双重检查锁定

  • 我有maploader,它使用索引进行查询 > maploader 主 这个工作绝对精细的地图不会加载,直到我第一次接触地图。 但是当我为地图添加索引的时候,地图就会被加载,而不管是不是触摸地图。在Hazelcast文档中,MapStoreConfig类中的InitialLoadMode配置参数有两个值:LAZY和eager。如果InitialLoadMode设置为LAZY,则在映射创建期间不加载