Home > Mobile >  Why is getMessage() executed automatically in my custom exception?
Why is getMessage() executed automatically in my custom exception?

Time:02-02

I have these classes:

public class NegativeNumberException extends Exception{
    
    NegativeNumberException()
    {
        System.out.println("Don't pass negative values!");
    }
    
    public String getMessage()
    {
        String message="NegativeNumberException";
        return message;
    }
}

public class Main {

    static void test(int n) throws NegativeNumberException
    {
        if(n<0) throw new NegativeNumberException();

        else System.out.println("Success");
    }
    public static void main(String[] args) {

        
        try
        {
             test(-5);
        }
        catch(NegativeNumberException nne)
        {
            System.out.println(nne);
        }
    }

}

This is the result:

Dont pass negative values!
NegativeNumberException: NegativeNumberException

I expected it to print NegativeNumberException once, i guess if i override getMessage it gets executed no matter what, is it correct or something else is going on?

CodePudding user response:

All objects have a toString() implementation. Because java.lang.Object itself (and Exception extends Throwable, and Throwable extends Object - all things eventually extend object) has this.

The Throwable class overrides the implementation of it with:

@Override public String toString() {
  String s = getClass().getName();
  String message = getLocalizedMessage();
  return (message != null) ? (s   ": "   message) : s;
}

and getLocalizedMessage() is implemented as:

public String getLocalizedMessage() {
  return getMessage();
}

whenever you 'append' an object to a string (with X Y, where the X expression has type String and Y is anything) is shorthand for X.concat(Y.toString()). Thus, you're calling toString there. You did not override it, so you get Throwable's implementation of it, which invokes getLocalizedMessage - which you also didn't override, so that calls getMessage(), hence, you get your text. Twice.

Some lessons:

  • Do System.out anything in exception constructors.
  • The message should not end in punctuation (and definitely not an exclamation mark - it's an exception. That something went wrong is assumed, no need to yell about it), and should not repeat or consist of the exception type. That information is already available; the message exists for additional information. If you have nothing to add, then don't have a message. An exception named NegativeNumberException should probably have the actual number as message, or possibly the param name. Something like:
public class NegativeNumberException extends Exception {
  public NegativeNumberException(String msg) {
    super(msg);
  }
}

and then in your test method:

if (n < 0) throw new NegativeNumberException("n: "   n);

Overriding getMessage and returning some string constant is almost never correct. Messages should rarely be constants, as they are meant for detailing the specifics of the problem, not for generally explaining what the exception represents (write some javadoc for that, and only if the name of the exception is not sufficient to figure it out, hence, nothing needed here).

  •  Tags:  
  • Related