在构造函数

时间:2015-08-02 08:14:14

标签: java

我有一个Singleton Logger类。

public class Logger {
  public static Logger INSTANCE = new Logger();

  private Logger() {
    ...
  }
}

我想登录我的构造函数,创建一个新实例。所以我的代码看起来像:

public class MyClass {
  public MyClass() {
    Logger.INSTANCE.log("MyClass created");
    ...
  }
}

我想知道这是否会破坏MyClass的静态实例。例如,如果我有:

public class MyOtherClass {
  private static MyClass myClass = new MyClass();
  ...
}

我担心由于静态变量初始化的未定义顺序,这可能会导致问题。因此,如果在myClass之前初始化Logger.INSTANCE,则myClass的构造将崩溃。是否有一些机制来防止这种情况发生或在构造函数中使用静态变量本身就很危险?有没有办法阻止用户在这种情况下创建MyClass的静态实例?

4 个答案:

答案 0 :(得分:4)

public class Logger {
  public static Logger INSTANCE = new Logger();

  private Logger() {
    ...
  }
}

的语法糖
public class Logger {
  public static Logger INSTANCE;
  static {
      INSTANCE = new Logger();
  }

  private Logger() {
    ...
  }
}

静态块设置类的静态成员,is guaranteed to run before your class is used

答案 1 :(得分:1)

我建议你像经典的单身人士一样包装你的Logger.INSTANCE:

public class Logger{

  private static Logger logger;

  private Logger(){

  }

  public static Logger getInstance(){
     if(logger==null){
         logger = new Logger();
     }
    return logger;
  }

}

这样,当您致电Logger.getInstance()时,您将永远无法获得null

如果您需要线程安全的单例:

public class Logger {
    private static class Holder {
        static final Logger INSTANCE = new Logger();
    }

    public static Logger getInstance() {
        return Holder.INSTANCE;
    }
}

这样你也永远不会得到null因为默认情况下Logger会在使用它之前被初始化,因为在这种情况下它将是其他类的依赖。

答案 2 :(得分:0)

  

因此,如果在Logger.INSTANCE之前初始化myClass,则myClass的构造将崩溃。

在初始化所有依赖的类之前,您无法初始化类。

  

是否有某种机制可以防止这种情况发生,或者在构造函数中使用静态变量本身是否存在危险?

在初始化之前你不能使用一个类(除非你在初始化代码中调用它)

  

在这种情况下,有没有办法阻止用户创建MyClass的静态实例?

你不能构造一个类的实例,直到它使用的类被初始化。

答案 3 :(得分:0)

无需担心破坏任何东西,JVM将确保正确的构造顺序。但是,如果访问我的多个线程,则存在创建多个实例的风险。改进代码我声明单例为final,并使用静态方法访问:

public class Logger {
  private static final Logger INSTANCE = new Logger();

  private Logger() {}

  public static Logger getInstance() {
      return INSTANCE;
  }
}