Singleton or static class?

C

Chris Berg

I have these options, both works fine, but I wonder which one would be
considered more 'correct':

1) // ordinary Singleton pattern

public final class MainClass{
private int something;
private MainClass instance;
private MainClass(){
-- do all initialization --
}
public static synchronized MainClass getInstance(){
if (instance==null) instance=new MainClass();
return instance;
}
public int getSomething(){
return something;
}
}


2) // static class, no instance

public final class MainClass
private static int something;
private MainClass(){} // never instantiate
static{
-- do all initialization --
}
public static int getSomething(){
return something;
}
}

Calling getSomething() is simpler in 2); in 1) I always have to obtain
the instance first, and I think a virtual method may be more expensive
in CPU time - however, 2) does not look very 'object oriented'. Of
course, in 1) the instance is an actual Object that can be treated as
such, for instance it has toString() etc, but if that is not needed,
would 2) be considered 'bad taste', and why ? Normally, you see static
methods used for utilities (i.e. java.lang.Math).

Chris
 
H

Heiner Kücker

Chris Berg
I have these options, both works fine, but I wonder which one would be
considered more 'correct':

1) // ordinary Singleton pattern

public final class MainClass{
private int something;
private MainClass instance;
private MainClass(){
-- do all initialization --
}
public static synchronized MainClass getInstance(){
if (instance==null) instance=new MainClass();
return instance;
}
public int getSomething(){
return something;
}
}


2) // static class, no instance

public final class MainClass
private static int something;
private MainClass(){} // never instantiate
static{
-- do all initialization --
}
public static int getSomething(){
return something;
}
}

Calling getSomething() is simpler in 2); in 1) I always have to obtain
the instance first, and I think a virtual method may be more expensive
in CPU time - however, 2) does not look very 'object oriented'. Of
course, in 1) the instance is an actual Object that can be treated as
such, for instance it has toString() etc, but if that is not needed,
would 2) be considered 'bad taste', and why ? Normally, you see static
methods used for utilities (i.e. java.lang.Math).

Chris

The double locking in your first version is deprecated.

Second version is ok.


Heiner Kuecker
Internet: http://www.heinerkuecker.de http://www.heiner-kuecker.de
JSP WorkFlow PageFlow Page Flow FlowControl Navigation: http://www.control-and-command.de
Java Expression Formula Parser: http://www.heinerkuecker.de/Expression.html
CnC Template Technology http://www.heinerkuecker.de/Expression.html#templ
 
S

Stefan Schulz

I have these options, both works fine, but I wonder which one would be
considered more 'correct':

1) // ordinary Singleton pattern

public final class MainClass{
private int something;
private MainClass instance;
private MainClass(){
-- do all initialization --
}
public static synchronized MainClass getInstance(){
if (instance==null) instance=new MainClass();
return instance;
}
public int getSomething(){
return something;
}
}

It's fine. :)
2) // static class, no instance

public final class MainClass
private static int something;
private MainClass(){} // never instantiate
static{
-- do all initialization --
}
public static int getSomething(){
return something;
}
}

Also ok.
Calling getSomething() is simpler in 2); in 1) I always have to obtain
the instance first, and I think a virtual method may be more expensive
in CPU time - however, 2) does not look very 'object oriented'. Of
course, in 1) the instance is an actual Object that can be treated as
such, for instance it has toString() etc, but if that is not needed,
would 2) be considered 'bad taste', and why ? Normally, you see static
methods used for utilities (i.e. java.lang.Math).

It's mainly a matter of taste. I prefer the first variant, since it is
more easily changed into something more object-oriented. Also, such
a Singleton can have other uses beyond the static methods. It could
implement interfaces, be passed around to other objects, and generally
is much more flexible. The overhead of calling getInstance() (or
something) is usually really negligable. Besides, you need not use a
static initializer, with all the awkwardness involved. (Cause a class
load in a static initializer, and you'll be suprised!)
 
M

Michael Borgwardt

The double locking in your first version is deprecated.

That's not double locking. That's single locking, which people try
to avoid by double locking due to the synchronization overhead.
And double locking is not "deprecated", it just didn't work in
the old Java memory model, but does in the new one.

But it's all pointless anyway, because the same effect can be achieved
without any synchronization overhead or locking by doing the
initialization in the declaration. It will still be executed when the
class is loaded, which is almost certainly when the getInstance()
method is first called, i.e. exactly where you want it to happen:

private MainClass instance = new MainClass();
 
C

Chris Berg

(Cause a class
load in a static initializer, and you'll be suprised!)

What do you mean by that? Do you mean a new class referenced for the
first time (and thus class-loaded) inside a static{..} block? Why is
that a problem?

Chris
 
S

Stefan Schulz

What do you mean by that? Do you mean a new class referenced for the
first time (and thus class-loaded) inside a static{..} block? Why is
that a problem?

Situations like this:

class A {
public static final B f;
public static final A g;

static {
f = new B();
g = new A();
}
}

class B {
public static final A f;
public static final B g;

static {
f = A.g;
g = A.f;
}
}

The same problem can become much less obvious, and quite devious.
After all, it only happens if class B is classloaded exactly this way,
when it might initialize cleanly when loaded by some other code path.
 
C

Chris Berg

Ahh, I see, it is a cross-reference prior to (or during)
class-loading!

Hmm.. Have you ever tried it? What WILL eventually happen? Stack
overflow? VM nervous breakdown? Nuclear meltdown? I would suppose the
VM should be able to either survive such a situation, or at least exit
with a meaningful message. Or would that be OS dependent?

Chris
 
S

Stefan Schulz

Hmm.. Have you ever tried it? What WILL eventually happen? Stack
overflow? VM nervous breakdown? Nuclear meltdown? I would suppose the
VM should be able to either survive such a situation, or at least exit
with a meaningful message. Or would that be OS dependent?

The result is actually well-defined. But it is completely contrary to
any expectation: The static final fields actually start off as null, but
then get reassinged. I actually spend two days tracking down that bug,
and henceforth saw the rationale behind the singleton patter. :)
 
C

Chris Berg

The result is actually well-defined. But it is completely contrary to
any expectation: The static final fields actually start off as null, but
then get reassinged. I actually spend two days tracking down that bug,
and henceforth saw the rationale behind the singleton patter. :)

Aha! I think you have a very good point here. As you mentioned
earlier, the circular reference can very well be much less obvious
than your example shows. And it is logical that the variable at first
is null, then later becomes assigned, hence no system-error-message.

I'm convinced!

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,182
Latest member
BettinaPol

Latest Threads

Top