如何在Java中定义自定义异常类,最简单的方法?

Posted

技术标签:

【中文标题】如何在Java中定义自定义异常类,最简单的方法?【英文标题】:How to define custom exception class in Java, the easiest way? 【发布时间】:2011-04-16 03:14:36 【问题描述】:

我正在尝试以最简单的方式定义自己的异常类,这就是我得到的:

public class MyException extends Exception 

public class Foo 
  public bar() throws MyException 
    throw new MyException("try again please");
  

Java 编译器是这样说的:

cannot find symbol: constructor MyException(java.lang.String)

我有一种感觉,这个构造函数必须继承自java.lang.Exception,不是吗?

【问题讨论】:

【参考方案1】:

不,您不会“继承”非默认构造函数,您需要在您的类中定义采用 String 的构造函数。通常,您在构造函数中使用 super(message) 来调用父构造函数。例如,像这样:

public class MyException extends Exception 
    public MyException(String message) 
        super(message);
    

【讨论】:

@vulkanino:不。默认构造函数是由编译器为每个没有定义自己的构造函数的类添加的。如果你定义了一个显式的构造函数,即使超类有它,你也不会得到默认值;如果你的类没有构造函数,即使超类没有它,你也会得到默认值。 if your class has no constructor, you get the default even if the superclass does not have it 最后一部分是不可能的,除非超类具有该类可访问的默认构造函数(可能是受保护的或受包保护的)。否则必须显式调用父构造函数之一,否则编译将失败。 请添加MyException(Throwable)MyException(String, Throwable) 构造函数以正确支持exceptions chaining。 将近 3 年后,没有添加任何额外的构造函数。 :( @BrandonIbbotson 你所说的“他们”是什么意思,他们是在哪里添加的?如果你所说的“他们”是超类构造函数,而“哪里”是子类,那么你就错了。超类构造函数不会隐式添加到子类。另外,我在前面的句子中看不到任何其他主题可以参考这些词。【参考方案2】:

我定义的一个典型的自定义异常是这样的:

public class CustomException extends Exception 

    public CustomException(String message) 
        super(message);
    

    public CustomException(String message, Throwable throwable) 
        super(message, throwable);
    


我什至使用 Eclipse 创建了一个模板,这样我就不必一遍又一遍地编写所有的东西。

【讨论】:

您可以在 Eclipse 中创建类时扩展 Exception,您将获得所有四个构造函数。您不需要模板。 我们什么时候应该使用第二个Consutructor而不是第一个?【参考方案3】:

如果您在 Eclipse 中使用新的类对话框,您只需将 Superclass 字段设置为 java.lang.Exception 并选中“Constructors from superclass”,它将生成以下内容:

package com.example.exception;

public class MyException extends Exception 

    public MyException() 
        // TODO Auto-generated constructor stub
    

    public MyException(String message) 
        super(message);
        // TODO Auto-generated constructor stub
    

    public MyException(Throwable cause) 
        super(cause);
        // TODO Auto-generated constructor stub
    

    public MyException(String message, Throwable cause) 
        super(message, cause);
        // TODO Auto-generated constructor stub
    


针对以下关于不在默认构造函数中调用super() 的问题,Oracle 有this to say:

注意:如果构造函数没有显式调用超类构造函数,Java 编译器会自动插入对超类的无参数构造函数的调用。

【讨论】:

为什么默认构造函数不需要调用super() "If the subclass constructor does not specify which superclass constructor to invoke then the compiler will automatically call the accessible no-args constructor in the superclass."【参考方案4】:

Java 平台的Inheritance 文章解释了这个原因:

"一个子类继承所有成员(字段、方法和嵌套 类)来自其超类。 构造函数不是成员,所以他们 不是子类继承的,而是超类的构造函数 可以从子类中调用。”

【讨论】:

【参考方案5】:
package customExceptions;

public class MyException extends Exception

    public MyException(String exc)
    
        super(exc);
    
    public String getMessage()
    
        return super.getMessage();
    


import customExceptions.MyException;

public class UseCustomException 

    MyException newExc=new MyException("This is a custom exception");

    public UseCustomException() throws MyException
    
        System.out.println("Hello Back Again with custom exception");
        throw newExc;       


    public static void main(String args[])
    
        try
        
            UseCustomException use=new UseCustomException();
        
        catch(MyException myEx)
        
            System.out.println("This is my custom exception:" + myEx.getMessage());
        
    

【讨论】:

这会返回什么? 它只会打印出来自 UseCusomException 的构造函数的“Hello Back Again with custom exception”,该异常将被抛出然后在 main 中捕获,它将打印出“这是我的自定义异常:这是一个自定义异常”。【参考方案6】:

异常类有两个构造函数

public Exception() -- 这会在没有任何附加信息的情况下构造一个异常。异常的性质通常是从类名中推断出来的。 public Exception(String s) -- 构造带有指定错误消息的异常。详细消息是描述此特定异常的错误条件的字符串。

【讨论】:

其实从Java 1.4开始,多了两个构造函数:public Exception(Throwable)public Exception(String, Throwable)。他们需要正确支持exceptions chaining。 @DaniloPiazzalunga 同意你的看法。来源:构造函数摘要docs.oracle.com/javase/1.5.0/docs/api/java/lang/Exception.html【参考方案7】:

如果从 Exception 继承,则必须提供一个以 String 作为参数的构造函数(它将包含错误消息)。

【讨论】:

我觉得你也应该加上理由。 其实这是不正确的。如果您的代码使用带有一个 String 参数的构造函数,那么您必须声明它。但是,Exception 子类 可以 定义为没有显式构造函数...因为 Exception 有一个无参数构造函数。【参考方案8】:

别忘了最简单的抛出异常的方法(你不需要创建一个类)

if (rgb > MAX) throw new RuntimeException("max color exceeded");

【讨论】:

以上是关于如何在Java中定义自定义异常类,最简单的方法?的主要内容,如果未能解决你的问题,请参考以下文章

Java自定义异常类以及异常拦截器

Java 求大神们解答:自定义异常,处理异常

java中如何自定义异常

Java学习笔记3.10.5 异常处理 - 自定义异常

java 自定义事件的触发及监听

自定义异常