Konrad Höffner
Konrad Höffner

Reputation: 12207

Java lazy initialization for nonstatic methods?

I recently fell in love with the lazy-loading technique that is used as follows:

public class SomeClass
{
  static class ComplexClassHolder
  {
   static ComplexClass complex = new ComplexClass(); // takes a long time
  }

 static double someMethod(int x, int y)
 {
  return ComplexClassHolder.complex.calculate(x,y);
 }

 public double quickMethod() // if only this method is called there is no initialization of the instance of ComplexClass
 {
  return 1.0+1.0;
 }
}

But is a similar technique also possible for nonstatic methods?

Example

import java.util.Random;

public class SomeClass
{
    final int seed;

    public SomeClass(int seed)
    {
        this.seed=seed;
    }

    class ComplexClassHolder
    {
        Random r = new Random(SomeClass.this.seed); // let's pretend this takes a long time
    }

    public double randomDouble()
    {
        return ComplexClassHolder.r.nextDouble();
    }
}

The problem is that the above is not possible, because ComplexClassHolder and ComplexClassHolder.r are not static. If I make them static however, I don't have access to SomeClass.this.seed.

I know I can do it with getInstance() and synchronization but if would really appreciate if the elegant technique possible in the static case could somehow be used here as well.

Upvotes: 4

Views: 875

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200148

The technique you describe relies on Java's lazy class loading (which is guaranteed by the spec) so it will only work for application-wide singletons. What you are trying to achieve is pass an instance variable into the lazy-inited object. If you still want it to be an application-wide singleton and initialized only once, you can still make it work by writing your seed to a static field that your static class will see.

Upvotes: 0

Torben
Torben

Reputation: 3913

What you see as "elegant" looks confusing and silly to experienced programmers.

When you look at the following example you see that there are no implicit side effects caused by the language or class loader specification. Everything it does is right there in the code you see. You also understand that trickery is not beautiful.

public synchronized double getNextDouble() {
    if (r == null) {
        r = new Random();
    }
    return r.nextDouble();
}

You might also realize that if you fall in love with a hammer, all your problems start to look like nails. :)

Upvotes: 4

Related Questions