2

That's how I do it (android code)

private volatile static WifiManager wm;

private static WifiManager wm(Context ctx) {
    WifiManager result = wm;
    if (result == null) {
        synchronized (WifiMonitor.class) { // the enclosing class
            result = wm;
            if (result == null) {
                result = wm = (WifiManager) ctx
                    .getSystemService(Context.WIFI_SERVICE);
                if (result == null) throw new WmNotAvailableException();
            }
        }
    }
    return result;
}

Bloch in Effective Java recommends :

// Lazy initialization holder class idiom for static fields
private static class FieldHolder {

    static final FieldType field = computeFieldValue();
}

static FieldType getField() {
    return FieldHolder.field;
}

This has the advantages of dispensing with the synchronization and that the JVM optimizes out the field access. The problem is that I need a Context object in my case. So :

  • Is there a way to adapt Bloch's pattern to my case (computeFieldValue() needs a param) ?
  • If not, is there a way to execute around ? The code is subtle and I'd rather have it in one place and pass only required behavior in
  • Last but not least - is there a way to enforce access to the cache field (wm) only via the wm() method ? So I can avoid NPEs and such. Other languages use properties for this
Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • That scheme depends on the FieldHolder class not being initialized until getField is called. However, there is considerable leeway in the JVM spec as to when class initialization can occur, so it could occur much earlier. – Hot Licks Dec 02 '13 at 19:52
  • Frankly, the technique using `synchronized` is "obvious", easy to understand, and doesn't depend on any obscure or undocumented behaviors. I see nothing wrong with it. You can always put the "insides" in a synchronized static method, if you wish, to compartmentalize it a bit more. – Hot Licks Dec 02 '13 at 19:58
  • @HotLicks: that's question 2 :) – Mr_and_Mrs_D Dec 02 '13 at 20:01

1 Answers1

0

You can do the following

static int param1;
static String param2;

public static void params(int param1, String param2) {
     this.param1 = param1;
     this.param2 = param2;
}

private static class FieldHolder {

    static final FieldType field = new FieldType(param1, param2);
}

static FieldType getField() {
    return FieldHolder.field;
}

Note: even simpler than this is to use an enum,

enum Singleton {
    INSTANCE;
}

or

class SingletonParams {
    static X param1;
}

enum Singleton implements MyInterface {
     INSTANCE(SingletonParams.param1, ...);
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130