Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在简单的单例实例化中获取ExceptionInInitializerError_Java_Exception_Static_Singleton_Initializer - Fatal编程技术网

Java 在简单的单例实例化中获取ExceptionInInitializerError

Java 在简单的单例实例化中获取ExceptionInInitializerError,java,exception,static,singleton,initializer,Java,Exception,Static,Singleton,Initializer,我一定在做一些很愚蠢的事情,但是当我尝试在我的Singleton中实例化一个对象时,我得到了一个ExceptionInInitializerError: class MySingleton { private static MySingleton instance = null; private OtherObject obj; // Do I instantiate obj here??? private MySingleton() { //obj = new Ot

我一定在做一些很愚蠢的事情,但是当我尝试在我的Singleton中实例化一个对象时,我得到了一个ExceptionInInitializerError:

class MySingleton {

  private static MySingleton instance = null;
  private OtherObject obj;

  // Do I instantiate obj here???
  private MySingleton() {
    //obj = new OtherObject();
  }

  // Or here?
  {
    //obj = new OtherObject();
  }

  // Or where? ...

  public static MySingleton getInstance() {
    if (instance == null)
      instance = new MySingleton();
    return instance;
  }

}
我应该在构造函数中创建另一个对象,还是对于单例来说它总是应该为空?我在构造函数和初始值设定项块中都得到了异常

这是主要的()


您应该在构造函数中实例化OtherObj。给出错误的确切代码是什么

编辑——以下内容对我有用

class MySingleton {

  private static MySingleton instance = null;
  private Integer obj;


  private MySingleton() {
    obj = new Integer(2);
  }


  public static MySingleton getInstance() {
    if (instance == null)
      instance = new MySingleton();
    return instance;
  }

}
然后我从主循环调用getInstance。你可能想看看


您应该在构造函数中实例化OtherObj。给出错误的确切代码是什么

编辑——以下内容对我有用

class MySingleton {

  private static MySingleton instance = null;
  private Integer obj;


  private MySingleton() {
    obj = new Integer(2);
  }


  public static MySingleton getInstance() {
    if (instance == null)
      instance = new MySingleton();
    return instance;
  }

}
然后我从主循环调用getInstance。你可能想看看


静态初始化部分用于初始化标记为Static的类的成员。因为OtherObject obj不是静态的,所以不应该在那里初始化它。正确的位置是在构造函数中初始化它


如果在构造函数中有
obj=new OtherObject()
时出现异常InInitializeError,则问题可能是另一个类(可能是OtherObject?)错误地初始化了静态成员。

静态初始化部分用于初始化标记为static的类的成员。因为OtherObject obj不是静态的,所以不应该在那里初始化它。正确的位置是在构造函数中初始化它


如果在构造函数中有
obj=new OtherObject()
时遇到异常InInitializerError,则问题可能是另一个类(可能是OtherObject?)错误地初始化了静态成员。

您可以通过消除风险来避免一些混淆(您目前在例外情况中为此付费)。既然您实际上只是返回静态实例,为什么不在运行时创建该静态实例(即不要等待null):

如果您注意到了,现在一切都是确定的和直接的。您的MySingleton.instance在运行时填充,并通过静态方法
MySingleton.getInstance()
访问

我意识到这与原始GOF设计模式书中的确切模式不匹配,但您会注意到该类的用法实际上是相同的

编辑:继其他答案和评论中提出的一些线程安全点之后,我将尝试说明问题和GOF书中最初提出的解决方案是如何非线程安全的。要获得更好的参考,请参阅我在ACM/Safari在线书架上拥有的。坦白地说,这是一个更好的解决方案比我略图中的例子更有趣,但是,嘿,我们只能努力

因此,假设我们有两个名为Thread1和Thread2的线程,并且,巧合的是,每个线程都会命中MySingleton.getInstance()方法。这在现代多核超线程系统中是完全可能的。现在,即使这两个线程碰巧同时到达此方法的入口点,也无法保证哪一个线程会到达任何特定语句。因此,您可以看到如下情况:

// Note that instance == null as we've never called the lazy getInstance() before.

Thread1: if (instance == null)
Thread2: if (instance == null) // both tests pass - DANGER
Thread1:     instance = new MySingleton();
Thread2:     instance = new MySingleton(); // Note - you just called the constructor twice
Thread1: return instance; // Two singletons were actually created 
Thread2: return instance; // Any side-effects in the constructor were called twice
Thread1: return instance;
Thread2: return instance;
if null测试中说明的问题称为a。您无法知道谁将在何时执行哪条语句。因此,这就像两条线程正在向悬崖赛跑

如果您查看我的示例的同一种检查,两个线程仍在同一时刻命中getInstance(),您会看到如下内容:

// Note that instance == null as we've never called the lazy getInstance() before.

Thread1: if (instance == null)
Thread2: if (instance == null) // both tests pass - DANGER
Thread1:     instance = new MySingleton();
Thread2:     instance = new MySingleton(); // Note - you just called the constructor twice
Thread1: return instance; // Two singletons were actually created 
Thread2: return instance; // Any side-effects in the constructor were called twice
Thread1: return instance;
Thread2: return instance;
简单化了,是的,但这是我的观点。对象在很久以前构造过一次,线程可以指望它的值是一致的。不存在竞争


注意:您仍然需要担心OtherObject的构造函数的内容。这里的教训是:并发性很难。如果您要使构造函数线程安全(这是您应该做的),请确保OtherObject的作者也对您表示同样的礼貌。

您可以通过消除风险来避免一些混淆(您目前在例外情况中为此付费)。既然您实际上只是返回静态实例,为什么不在运行时创建该静态实例(即不要等待null):

如果您注意到了,现在一切都是确定的和直接的。您的MySingleton.instance在运行时填充,并通过静态方法
MySingleton.getInstance()
访问

我意识到这与原始GOF设计模式书中的确切模式不匹配,但您会注意到该类的用法实际上是相同的

编辑:继其他答案和评论中提出的一些线程安全点之后,我将尝试说明问题和GOF书中最初提出的解决方案是如何非线程安全的。要获得更好的参考,请参阅我在ACM/Safari在线书架上拥有的。坦白地说,这是一个更好的解决方案比我略图中的例子更有趣,但是,嘿,我们只能努力

因此,假设我们有两个名为Thread1和Thread2的线程,并且,巧合的是,每个线程都会命中MySingleton.getInstance()方法。这在现代多核超线程系统中是完全可能的。现在,即使这两个线程碰巧同时到达此方法的入口点,也无法保证哪一个线程会到达任何特定语句。因此,您可以看到如下情况:

// Note that instance == null as we've never called the lazy getInstance() before.

Thread1: if (instance == null)
Thread2: if (instance == null) // both tests pass - DANGER
Thread1:     instance = new MySingleton();
Thread2:     instance = new MySingleton(); // Note - you just called the constructor twice
Thread1: return instance; // Two singletons were actually created 
Thread2: return instance; // Any side-effects in the constructor were called twice
Thread1: return instance;
Thread2: return instance;
if null测试中说明的问题称为a。您无法知道谁将在何时执行哪条语句。因此,这就像两条线程正在向悬崖赛跑

如果您查看我的示例的同一种检查,两个线程仍在同一时刻命中getInstance(),您会看到如下内容:

// Note that instance == null as we've never called the lazy getInstance() before.

Thread1: if (instance == null)
Thread2: if (instance == null) // both tests pass - DANGER
Thread1:     instance = new MySingleton();
Thread2:     instance = new MySingleton(); // Note - you just called the constructor twice
Thread1: return instance; // Two singletons were actually created 
Thread2: return instance; // Any side-effects in the constructor were called twice
Thread1: return instance;
Thread2: return instance;
简单化了,是的,但这是我的观点。