1

I want to create a custom exception to use in my code. Defining it like this

public class MyException extends Exception {}

provides only empty constructor, which is still usable. So I need to define all the constructors manually. Is there a list of constructors that I should override and should I do it like that?

MyException(/* args */) {
    super(/* same args */);
}
Sergei Kozelko
  • 691
  • 4
  • 17
  • 1
    String constructor, Exception Constructor, and the Combination of the Two. Allows you set error, set pass trace of exception, and the combination. Just my opinion. – Compass Jun 22 '16 at 19:50

3 Answers3

3

Your sample looks fine.

There are no scripted rules for it, just override constructors that you need to use in your application, you can see list of constructors here for java 8

No-arg constructor

I think it always make sense to override this constructor, because it is always good to override no-arg constructor as it is the first thing that you might want to use if you are not sure what kind of object you want to create.

But generally it is bad practice to throw exception without message, so I will recommend you to change it to private/protected to explicitly declare that you don't want exceptions to be created without message.

Exception()
// Constructs a new exception with null as its detail message.

Constructor with message

I would override this one first, because it allows to pass additional info with exception and it is very handy.

Exception(String message)
// Constructs a new exception with the specified detail message.

Re-throwing exception

You can override these if you need to re-throw your exception with/without additional information.

Exception(String message, Throwable cause)
// Constructs a new exception with the specified detail message and cause.

Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
// Constructs a new exception with the specified detail message, cause, suppression enabled or disabled, and writable stack trace

enabled or disabled.


Exception(Throwable cause)
// Constructs a new exception with the specified cause and a detail message of (cause==null ? null : cause.toString()) (which typically

contains the class and detail message of cause).

gevorg
  • 4,835
  • 4
  • 35
  • 52
  • Care to explain why it always makes sense to implement a no-arg constructor? If you don't intend to use it, or even prevent it from being used, I don't see any reason to implement it. Constructors don't override, since they're not inherited. (... and have a different name...) – Arjan Jun 23 '16 at 00:31
  • @Arjan thanks for comment, added more info on that, my assumption was that it is obvious, but I might be wrong there :) – gevorg Jun 23 '16 at 02:06
  • Hm it doesn't make things much clearer to me, perhaps my question wasn't clear. What I don't understand, is: Why would you implement the no-arg constructor as private if you don't want exceptions to be created without message (or cause)... if you can **achieve the same simply by not implementing the no-arg constructor at all**? What's the benefit? You can't use `new CustomException();` either way? – Arjan Jun 23 '16 at 02:24
  • @Arjan Well, because it is always good design to declare things explicitly to make it clear what your intentions are, additionally you can have reusable code fragment there that might be used in other constructors, additionally if you don't declare any other constructor compiler adds default one automatically. – gevorg Jun 23 '16 at 02:28
3

It all depends on what you want to store as information in your exception.

But generally, allowing to provide a root cause is a good idea. And, unless you want more structured information in the exception (like a code or something like that), a message is a good idea, too.

So yes, providing the same constructors as Exception, and delegating to the corresponding super constructor, is a good rule of thumb.

You could also encourage (or force) callers to always pass a message by not providing any constructor without a message argument, too.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Your first example will work if you only intend to use throw new MyCustomException(), but in case of exceptions... you might want to provide more information. It can make debugging easier.

If someone else is to use your exception class, they will probably expect to be able to use more explicit messages, or pass it a cause in case they're rethrowing. Or if someone else has to debug your code, your chance of not being strangled is much better if it doesn't throw exceptions without message or cause.

For example a custom exception I used in my last project,

public final class CryptorException extends Exception {

    private static final long serialVersionUID = 1L;

    public CryptorException(String message) {
        super(message);
    }

    public CryptorException(Throwable cause) {
        super(cause);
    }

    public CryptorException(String message, Throwable cause) {
        super(message, cause);
    }
}

That's all. It takes a couple of seconds and very little effort. Note though how I didn't implement a constructor without parameter. If you want it, you'll need to add it.

Technically, the constructors don't override anything because constructors are not inherited to begin with.

For an explanation of the serialVersionUID, see this question. If you're not serializing anything, you don't need to care about it.

Community
  • 1
  • 1
Arjan
  • 823
  • 1
  • 7
  • 18