19

How can I throw an exception from an enum constructor? eg:

public enum RLoader {
  INSTANCE;
  private RLoader() throws IOException {
   ....
  }
}

produces the error

Unhandled exception type IOException

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
tekumara
  • 8,357
  • 10
  • 57
  • 69
  • 7
    Why would you want to do that? To me this sounds like an abuse of the enum concept. Enum values are supposed to be constants, whose creation is not dependent on anything. Even if technically you _could_ do that (by throwing an unchecked exception instead of a checked one), I would suggest you revise your design. If you are trying to implement a Singleton via this enum, it is better to implement it by hand as a normal class. – Péter Török Aug 22 '10 at 23:33
  • 2
    I'm implementing a Singleton, but how would implementing it by hand as a normal class be any better? I would still have to throw an exception from code called by a static initializer. You can throw unchecked exceptions from an enum constructor. – tekumara Aug 22 '10 at 23:53
  • there's something *icky* about getting an exception thrown merely by accessing an enum value. Not so bad when it's a singleton getInstance() method. – Kirk Woll Aug 22 '10 at 23:55
  • 1
    @Péter Török how would implementing it by hand as a normal class be any better? I think it's ok to use enum to implements a singleton, as said. – bylijinnan Jul 17 '15 at 01:08
  • @PéterTörök for my understanding, especially for this case, why do you think "If you are trying to implement a Singleton via this enum, it is better to implement it by hand as a normal class."? – Abhishek Garg Oct 28 '19 at 21:22

3 Answers3

23

Because instances are created in a static initializer, throw an ExceptionInInitializerError instead.

throw new ExceptionInInitializerError();
2240
  • 1,547
  • 2
  • 12
  • 30
tekumara
  • 8,357
  • 10
  • 57
  • 69
4

I have a case where I want to use enums as keys in some settings classes. The database will store a string value, allowing us to change the enum constants without having to udpate the database (a bit ugly, I know). I wanted to throw a runtime exception in the enum's constructor as a way to police the length of the string argument to avoid hitting the database and then getting a constraint violation when I could easily detect it myself.

public enum GlobalSettingKey {
    EXAMPLE("example");

    private String value;

    private GlobalSettingKey(String value) {
        if (value.length() > 200) {
            throw new IllegalArgumentException("you can't do that");
        }
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }
}

When I created a quick test for this, I found that the exception thrown was not mine, but instead was an ExceptionInInitializerError.

Maybe this is dumb, but I think it's a fairly valid scenario for wanting to throw an exception in a static initializer.

silent_h
  • 143
  • 2
  • 6
  • 3
    But the original exception is chained with ExceptionInInitializerError, so if you call 'getCause()' on it, you will get the original exception. – shrini1000 Apr 19 '12 at 06:24
1

That scenario cannot work.

You are trying to throw a checked Exception from the constructor.

This constructor is called by the INSTANCE enum entry declaration, so the checked exception cannot be handled correctly.

Also it is in my opinion it's bad style to throw Exceptions from a constructor, as a constructor normally shouldn't do any work and especially not create errors.

Also if you want to throw an IOException I assume that you want to initialize something from a file, so you should perhaps consider this article on dynamic enums.

Johannes Wachter
  • 2,715
  • 17
  • 17
  • 3
    If it's bad style to throw Exceptions from a constructor, what do you do when one of the arguments to your constructor is invalid and will prevent your class from functioning? I prefer to fail fast by throwing an exception so I can get a meaningful stack trace. That being said, I agree with you that the OP shouldn't be trying to throw an exception in an **enum's** constructor. – Kirk Woll Aug 22 '10 at 23:57
  • @Kirk Woll: I prefer using factory methods that ensure the validity of the parameters. Also I was mainly focussing on checked Exceptions, RuntimeException would be a better way to signal a verification error IMO. – Johannes Wachter Aug 23 '10 at 00:00
  • 2
    Exclusive use of factory methods for all object instantiation? Oh the poor woebegotten **new** operator. :) – Kirk Woll Aug 23 '10 at 00:05
  • @Kirk Woll: No not for all instantiations, but for the once where special validation for the constructor parameters is needed. Normally I'm using the principle of not doing work inside constructors besides assignments, so I'm not programming as fail-fast as you :) – Johannes Wachter Aug 23 '10 at 00:13
  • 5
    Is there really a difference between throwing an exception from a factory method versus a constructor? You say tomato I say tomatoe – matt b Aug 23 '10 at 01:18
  • About factory methods, yes they are preferred by some over constructors. From Effective Java book "Item 1: Consider static factory methods instead of constructors". Of course not always and not explicitly with exceptions, that is another matter. – Anddo May 01 '20 at 21:03