51

I am facing a use case where I would like to declare a static finalfield with an initializer statement that is declared to throw a checked exception. Typically, it'd look like this:

public static final ObjectName OBJECT_NAME = new ObjectName("foo:type=bar");

The issue I have here is that the ObjectName constructor may throw various checked exceptions, which I don't care about (because I'd know my name is valid, and it's allright if it miserably crashes in case it's not). The java compiler won't let me just ignore this (as it's a checked exception), and I would prefer not to resort to:

public static final ObjectName OBJECT_NAME;
static {
    try {
        OBJECT_NAME = new ObjectName("foo:type=bar");
    } catch (final Exception ex) {
        throw new RuntimeException("Failed to create ObjectName instance in static block.", ex);
    }
}

Because static blocks are really, really difficult to read. Does anyone have a suggestion on how to handle this case in a nice, clean way?

kohane15
  • 809
  • 12
  • 16
Romain
  • 12,679
  • 3
  • 41
  • 54
  • My personal solution is to throw a `CheckedExceptionsAreAPainInTheAssSometimesException`, which is a runtime exception. The program will then just crash. – Bassinator Oct 18 '17 at 01:34

4 Answers4

53

If you don't like static blocks (some people don't) then an alternative is to use a static method. IIRC, Josh Bloch recommended this (apparently not in Effective Java on quick inspection).

public static final ObjectName OBJECT_NAME = createObjectName("foo:type=bar");

private static ObjectName createObjectName(final String name) {
    try {
        return new ObjectName(name);
    } catch (final SomeException exc) {
        throw new Error(exc);
    }  
}

Or:

public static final ObjectName OBJECT_NAME = createObjectName();

private static ObjectName createObjectName() {
    try {
        return new ObjectName("foo:type=bar");
    } catch (final SomeException exc) {
        throw new Error(exc);
    }  
}

(Edited: Corrected second example to return from method instead of assign the static.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • 2
    I didn't think about it, despite now that I read it I'm 100% certain I've used this approach a long time ago. I'll use this as I don't like static blocks and also like my code to be readable by beginners (You never know who'll maintain you code after yourself :)). – Romain Dec 08 '09 at 14:17
  • gives me a compiler error of "must return a result of type ObjectName" -- would a simple solution be to have `return null` in the `catch` block? But then a little odd to debug – Don Cheadle Nov 12 '14 at 22:54
  • I think you are referring to Item 59: Avoid unnecessary use of checked exceptions (Effective Java, 2nd Edition). In that item, Bloch is advising the author of the code that throws an exception to consider if its clients 'can take some useful action once confronted with the exception'. That is different from this case, where the question isn't the legitimacy of the exception thrown, but how best to handle the exception. From looking at the documentation for `java.lang.Error`, I get the feeling throwing an error isn't the best thing to do here. – nullstellensatz Sep 19 '15 at 16:45
  • `Error`s should be used for 'abnormal conditions' that indicate 'serious problems' with the program. In the examples Bloch gives, `AssertionError`s are only thrown in code that should never run, e.g. in the `default` section of a `switch` block, or within a private constructor of an un-instantiable class. IMHO, given the fact that the exceptional condition in this case is not improbable, throwing a `RuntimeException` is more appropriate than throwing an `Error`. – nullstellensatz Sep 19 '15 at 16:45
  • @nullstellensatz This is from six years ago! I was referring to the Bloch advice (may have changed in the last decade) about creating static methods for construction instead of instance initialisers. Searching through 2nd Ed of Effective Java on the Kindle it doesn't actually appear to be in that book. / The intention of the *thrown* exception is to signal that the class is broken and it must die. That's an error. (Will get wrapped in `java.lang.ExceptionInInitializerError`.) `Error` is also much more readable than nonsense `RuntimeException`. – Tom Hawtin - tackline Sep 19 '15 at 17:26
18

Your code is perfectly valid. I don't find it difficult to read. Other ways would only make it more worse. They're only difficult to read for starters, because most of them are not familiar with that. Just follow the standard conventions with regard to ordering of the elements in the code. E.g. do not put static initializers halfway or at the whole bottom of the code and also do not have multiple of them spreading over the class. Just put one at top, after static declarations.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • This is a very valid point (so I voted it up despite not accepting it), ant the GPP is also best stated. I won't use that method because as you say, this is only difficult to understand/read for beginners... And I can't ensure the people who'll maintain it after me are experienced :). – Romain Dec 08 '09 at 14:20
  • I am not sure if I would prefer that. With refactoring it into a `private static` method you risk losing the oversight. Normal practice is that those kind of methods (utility methods) are placed at the whole bottom of the class. But OK, nowadays you have IDE's so that you can just click ahead. – BalusC Dec 08 '09 at 14:33
5

static blocks aren't difficult to read. So I'd recommend that solution. However, you can wrap your object in another object, for example ObjectNameWrapper which shares an interface with your ObjectName, and whose constructor calls your ObjectName constructor, hiding all checked exceptions that occur. But again, I'd go for the static option.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
4

You can use a method annotated with Lombok's @SneakyThrows

public static final ObjectName OBJECT_NAME = createObjectName();

@SneakyThrows(SomeException.class)
private static ObjectName createObjectName() {
    return new ObjectName("foo:type=bar");
}

This annotation makes a checked exception behaves like an unchecked one.

mturina
  • 121
  • 1
  • 4