为什么我的自定义异常中的getMessage()方法会自动执行?

3
我有这些类:
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);
        }
    }

}

这是结果:

Dont pass negative values!
NegativeNumberException: NegativeNumberException

我原本期望它只会打印一次NegativeNumberException,但我猜如果我重写了getMessage方法,那么无论如何它都会被执行,是这样吗?还是有其他情况发生了?


1
一个是类的名称,另一个是getMessage的结果。将getMessage更改为其他内容,您将看到差异。 - Silvio Mayolo
@SilvioMayolo 我的问题是,为什么它会打印出NegativeNumberExceptiongetMessage中的任何内容,尽管我没有像 nne.getMessage() 这样调用它? - Rafik Bouloudene
2
你的代码中没有调用 getMessage。你调用的是 println,它会调用 toString,然后再调用 getMessage 并对其进行自己的操作。 - Silvio Mayolo
1个回答

7

所有对象都有一个toString()实现。因为java.lang.Object本身(以及Exception extends ThrowableThrowable extends Object - 所有东西最终都扩展自Object)都有它。

Throwable类通过以下方式覆盖了它的实现:

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

getLocalizedMessage() 是这样实现的:

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

每当你使用 X + Y 将一个对象附加到字符串中(其中 X 表达式的类型为 String,而 Y 可以是任何类型),这相当于调用 X.concat(Y.toString())。因此,你在那里调用了 toString。由于你没有重写它,所以你得到了 Throwable 类的实现方式,该方法调用 getLocalizedMessage - 你也没有重写它,因此调用 getMessage(),从而获取文本。两次。
一些教训:
  • 不要在异常构造函数中输出 System.out。异常会打印到某个地方,如果需要打印,会自动打印。如果一个异常“终止”了你的 static void main(String[]) 方法,则 java 会为你打印它。
  • 消息不应以标点符号结尾(绝对不能是感叹号——这是一个异常,假定出现了问题,不需要大喊大叫),也不应重复或包含异常类型。该信息已经可用;消息存在是为了提供额外信息。如果没有要添加的内容,则不需要消息。名为 NegativeNumberException 的异常应该将实际数字作为消息,或者可能是参数名称。例如:
public class NegativeNumberException extends Exception {
  public NegativeNumberException(String msg) {
    super(msg);
  }
}

然后在你的测试方法中:

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

覆盖 getMessage 并返回某些字符串常量几乎永远不是正确的。消息应该很少是常量,因为它们旨在详细说明问题的具体情况,而不是一般性地解释异常表示什么(为此编写一些javadoc,只有当异常名称不足以弄清它时才需要,因此,这里不需要任何内容)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接