Question

I find myself choosing between the two following design patterns a lot:

static {
    try {
        foo();
    }
    catch(Exception exc) {
        throw new RuntimeException(exc.getMessage());
    }
}

and

TheConstructor() throws SomeException {
    if(alreadyInited) {
        return;
    }
    alreadyInited = true;
    foo();
}

The problem is I really do want to initialize stuff once per class - so statically, I think - such as setting up a logger, loading some map from a file, etc. - and I really do want the program to halt if this operation fails. Both of these design patterns seem kludgey (the first one more obviously so), so I'm wondering if there's a better way to do this.

Was it helpful?

Solution

Is allowing exceptions in static class constructors to escape a proper design pattern?

I would say No.

First, wrappering a checked exception in that context means that if something goes wrong you will get a class initialization failure.

  • An exception that propagates out of the class initalizer cannot be caught and handled directly.

  • An uncaught exception during class initialization is not recoverable. Even if you could catch and handle the exception, the class and (I think) all others that depend on it / they will be left in a state where they cannot be initialized, and hence cannot be used. That's effectively "game over" for (at least) the classloader, and possibly the entire JVM.

The bigger picture is that this probably represents an inappropriate use of statics. There are better ways to handle this problem; e.g.

  • Do the initialization using an explicit call (in a place where you can catch and handle the exception), rather than relying on class initialization.

  • Get rid of the static (and potentially the singleton class that wraps it) and use dependency injection.

OTHER TIPS

The factory pattern can help you here. You can still throw RunTime exceptions, although I would throw an exception called "CouldNotCreate" along with some cool info on what went wrong.

Your first example looks fine to me. If your class absolutely needs to do foo() to be usable, then if it can't do foo(), it's not usable. If it's not usable, then it must not be used. Throwing an exception from the static initializer is a straightforward and effective way of making sure that the class isn't used.

It's unfortunate that Java doesn't allow checked exceptions to be thrown from static initializers. I don't see why that should be the case.

In this case I choose the singleton pattern FOR the "configuration".

But the logic inside the constructor is very strange, the static block is more clean IMHO, but I think it is not easy to test. Be careful.

You could make the second a little less kludgey like this:

static boolean isStaticInit = false;
static void staticInit() throws InitException {
    if (isStaticInit) return;

    // [init loggers, map, etc...throw InitException as appropriate]

    isStaticInit = true;
}

MyClass() throws InitException {
    staticInit();

    // ...
}

Note there is a subtle difference between your first and second options. In the first option, the static{} block is called when the class is first loaded, while for the second option, the init code isn't called until the first class instance is constructed. This could make a difference if you have code that calls, say, MyClass.myStaticMethod(). With option 1, the call would trigger class initialization; with option 2, it won't.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top