The first solution (I believe) is not thread safe.
The second solution is (I believe) thread safe, but may not work if you have complex initialization dependencies in which MyClass.getInstance() is called before the static MyClass initializations are complete. This is probably the problem you saw.
Both solutions allow someone to create another instance of your (essentially) singleton class.
More reliable solution:
class MyClass { private static MyClass instance; private MyClass() { } public synchronized static MyClass getInstance() { if (instance == null) { instance = new MyClass(); } return instance; } }
In a modern JVM, the cost of acquiring a lock is minimal, provided that there is no competition over the lock.
EDIT @Nate makes my statement about static initialization order, which can cause problems. Consider the following (pathological) example:
public ClassA { public static ClassB myB = ClassB.getInstance(); public static ClassA me = new ClassA(); public static ClassA getInstance() { return me; } } public ClassB { public static ClassA myA = ClassA.getInstance(); public static ClassB me = new ClassB(); public static ClassB getInstance() { return me; } }
There are two possible initialization options for these two classes. Both results invoke a static method that is called before the static method class initialization has been performed. This will initialize ClassA.myB or ClassB.myA to null .
In practice, the cyclic dependencies between statics are less obvious. But the fact remains: if there is a cyclic dependency: 1) the Java compiler will not be able to tell you about it, 2) the JVM will not tell you about it. Rather, the JVM will silently choose the initialization order without "understanding" the semantics of what you are trying to do ... maybe something unexpected / wrong.
EDIT 2 . This is described in JLS 12.4.1 as follows:
As the example in section 8.3.3.3 shows, the fact that the initialization code is unlimited allows you to create examples where the value of a class variable can be observed when it still has an initial default value before its initialization expression will be but such examples in practice are rare. (Such examples can also be constructed, for example, to initialize variables, see the Example at the end of Β§ 12.5). Full language permissions are available in these initializers; programmers should exercise some caution ....