10

I am recently thinking about if throwing constructor from Java is good or not. Currently this is what I gathered:

  1. Can constructors throw exceptions in Java?

    Here, Mr. StackOverflow (aka Jon Skeet) does not seem to hold anything against it, but he did hint about having subclass throwing exceptions. What will happen (anything bad?) when subclass throws exceptions?

  2. http://futuretask.blogspot.com/2006/05/java-tip-10-constructor-exceptions-are.html

    This blog post "Constructor Exceptions are Evil" tells me a way to show that constructor exceptions could be dangerous. However, the example seem to be really esoteric. Is there any real danger here?

  3. I am thinking that if static factory methods (Effective Java 2nd ed., Item 1) are used instead of public constructors, we could safely remove the exceptions from constructors to the static factory method. Is this a valid way to avoid constructor exceptions and is this useful or used in anywhere?

Any inputs are helpful & appreciated. Thanks!

Community
  • 1
  • 1
zw324
  • 26,764
  • 16
  • 85
  • 118
  • Can you give us an example of what you are thinking about doing? Answers to questions like this is really a judgement call based on the problem. – Brad Sep 23 '11 at 16:31
  • @Brad: I am just thinking about general concerns. For example, in the second item I linked to a post, which showed a way to access a half built object. Although the method in the post is uncommon, it shows a potential error. Also, I am thinking that if we throw exceptions from constructor, we are putting logic inside the constructor. Could it be safer/better if we just use static factory method to take the potentially dangerous logic outside of the constructor? Thanks! – zw324 Sep 23 '11 at 16:39

3 Answers3

8

My point about a subclass throwing an exception is a situation like this:

public class Parent {
    private final InputStream stream;

    public Parent() {
        stream = new FileInputStream(...);
    }

    public void close() throws IOException {
        stream.close();
    }
}

public class Child extends Parent {
    public Child() {
        // Implicit call to super()
        if (someCondition) {
            throw new RuntimeException();
        }
    }
}

Now the Child class really should call close() if it's going to throw an exception. Of course, if close() is overridden by yet another layer of inheritance, that could also cause problems. Just another example of how inheritance gets messy.

I still think it's basically fine for constructors to throw exceptions. Even your second link was more about an evil way of capturing the not-successfully-constructed object rather than really about constructor exceptions being evil - it certainly doesn't give any reasons for not throwing exceptions from constructors. It doesn't even give the messy situation I mentioned.

Factory methods could potentially help, but as far as the caller is concerned the result is the same: they don't get to see the partially-constructed object. Unless you really need to do something like clean-up on an object which was constructed but then failed some element of validation, I don't think that should be a reason to use factory methods instead of constructors. (There are other reasons to do so, but that's a different matter.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Shouldn't finalize be implement to counter such cases i.e. your example shows to call close() by contract, so if something goes wrong in the constructor of child class, shouldn't super class provide some mechanism to clear such resources to get close or document the behavior for implementers of sub class to implement try/finally block, close the fields and then throw the exception? – Usman Saleem Sep 23 '11 at 17:08
  • @UsmanSaleem: I don't think finalizers are the answer - I don't want resources to be open for an arbitrary length of time on exception; I want them to be cleaned up immediately. – Jon Skeet Sep 23 '11 at 17:37
  • I kinda agree with your point. Honestly in practice, I avoid throwing exceptions from constructors, I tend to use initResource or similar post constructor methods. – Usman Saleem Sep 23 '11 at 17:47
  • @UsmanSaleem: That leads to a design smell where a fully-constructed object isn't *actually* ready for use though... – Jon Skeet Sep 23 '11 at 18:05
  • :-D Laughed Out Loud!, Yes Jon, you are quite right actually. – Usman Saleem Sep 23 '11 at 18:07
8

There is nothing wrong with exceptions in constructors (or factory methods, either way is fine). sometimes, doing too much work in a constructor can be a poor design, and may make sense to move to a factory method.

the only thing that point 2 proves is that exceptions in constructors are not an adequate security mechanism for protecting a class from evil usage. however, there are any number of ways to subvert such a design, which is why the only way to truly run secure code in java is running with a SecurityManager. so point 2 is just a straw man argument.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
1

I believe throwing exceptions from constructors is fine, more so the one's which checks for the preconditions to a successful object creation, example IllegalArgumentException. However, I do not believe that constructors are the right place to handle business logic or throw business exception/ custom exceptions.

As for the reasons cited to not throw an exception, IMHO they are quite contrived; bottom line is if a careless developer wishes to do something evil he can find numerous ways to do it and there's no stopping till the developer does a self review of the code/ follows best practices.

Scorpion
  • 3,938
  • 24
  • 37