【问题标题】:The throws keyword for exceptions in JavaJava 中异常的 throws 关键字
【发布时间】:2010-01-01 17:13:27
【问题描述】:

当你这样做时:

public class Blah {

    public void doBlah() throws BlahException {

    }

}

添加throws BlahException 的真正作用是什么?

它基本上是否将任何例外归为一类?即如果有异常,不管它是什么,总是使用BlahException抛出?

【问题讨论】:

    标签: java exception


    【解决方案1】:

    它告诉您的类的客户 DoBlah 方法可以抛出 BlahException 或 任何其他扩展它的异常

    如果它是一个已检查的异常,编译器将要求他们将对该方法的调用包装在一个 try/catch 块中。如果未选中,他们可以选择不捕获异常,但他们必须注意,如果不这样做,它将在调用堆栈中进一步冒泡。

    它没有说明 NullPointException 或错误等未经检查的异常。那些总是可以抛出的。 throws 子句中不需要它们。

    这段代码展示了它是如何工作的:

    ExceptionDemo.java:

    package exceptions;
    
    public class ExceptionDemo
    {
        public static void main(String[] args)
        {
            ExceptionDemo demo = new ExceptionDemo();
    
            try
            {
                // Removing the try/catch will result in a compilation error
                demo.doChecked();            
            }
            catch (CheckedException e)
            {
                e.printStackTrace();
            }
    
            // Note: Not inside a try/catch, in spite of the throws clause
            demo.doUnchecked();
        }
    
        public void doChecked() throws CheckedException
        {
            System.out.println("doing something that may throw a checked exception");
        }
    
        // Note: "throws" clause is unnecessary for an unchecked exception
        public void doUnchecked() throws UncheckedException
        {
            System.out.println("doing something that may throw an unchecked exception");
        }
    }
    

    CheckedException.java:

    package exceptions;
    
    public class CheckedException extends Exception
    {
        public CheckedException()
        {
            super();
        }
    
        public CheckedException(String message)
        {
            super(message);
        }
    
        public CheckedException(String message, Throwable cause)
        {
            super(message, cause);
        }
    
        public CheckedException(Throwable cause)
        {
            super(cause);
        }
    }
    

    UncheckedException.java:

    package exceptions;
    
    public class UncheckedException extends RuntimeException
    {
        public UncheckedException()
        {
            super();
        }
    
        public UncheckedException(String message)
        {
            super(message);
        }
    
        public UncheckedException(String message, Throwable cause)
        {
            super(message, cause);
        }
    
        public UncheckedException(Throwable cause)
        {
            super(cause);
        }
    }
    

    【讨论】:

    • 奇怪的是,我在 Java 教程 (java.sun.com/docs/books/tutorial/java/TOC.html) 中完全没有提到异常。多么奇怪的遗漏。
    • 只是出于好奇,您究竟如何指定(用户定义的)异常应该被选中还是不选中?是让它出现在“抛出”部分那么简单,还是你必须在异常类本身中做些什么?
    • @skaffman 异常包含在基本 Java 类 (java.sun.com/docs/books/tutorial/essential/index.html) 中,而不是学习 Java 语言。
    • @Platinum Azure 未经检查的异常是从 java.lang.RuntimeException 或 java.lang.Error 扩展而来的异常,即在定义用户定义的异常时,它归结为您指定为超类的异常。
    • 啊,所以如果它是从 java.lang.Exception 扩展的,并且我在 throws 子句中指定它,它一定是一个检查异常?
    【解决方案2】:

    整体思路是,没有throws关键字,方法引发的异常无法在方法外处理。

    不是吗?

    【讨论】:

      【解决方案3】:

      没有。 throws BlahException 子句告诉编译器你的函数可能抛出一个 BlahException 并且这应该被调用者捕获。例如:

      class ExceptionThrower
      {
          void someFunction()
          {
              for(int i =0; i<10;i++)
                  if(i==4) throw new Exception();
          }
      
          public static void main(String args[])
          {
              new ExceptionThrower().someFunction();
          }
      }
      

      这个程序不会编译,因为它可以抛出一个Exception类型的异常,而且这个异常既没有被捕获也没有被声明为抛出。

      但是,下面的代码可以正常编译。

      class ExceptionThrower
      {
          void someFunction() throws Exception
          {
              for(int i =0; i<10;i++)
                  if(i==4) throw new Exception();
          }
      
          public static void main(String args[])
          {
              try
              {
                  new ExceptionThrower().someFunction();
              }
              catch(Exception e)
              {
                  e.printStackTrace();
              }
      
          }
      }
      

      本质上,你是在告诉编译器这个函数可能抛出一个不在函数内部处理的异常。这些类型的异常都是java.lang.Exception 的子类,被称为已检查异常。其他表示由程序本身的错误而不是由格式错误等条件引起的灾难性故障的异常是java.lang.RuntimeException 的子类,它们被称为未经检查的异常。简而言之,未经检查的异常可以在方法签名中没有throws 子句的情况下抛出,而任何检查的异常都必须在其中指明。

      有关已检查与未检查异常的讨论,请参阅http://www.javapractices.com/topic/TopicAction.do?Id=129

      【讨论】:

      • 对于未经检查的异常情况并非如此。出于文档原因,它们可以在方法签名中声明,但不需要被客户端捕获。
      【解决方案4】:

      您的方法doBlah() 需要有可以throw BlahExceptionBlahException 的任何子类的东西。这告诉doBlah() 的调用者通常要小心将代码包装在try-catch 中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-07
        • 2011-08-09
        • 2011-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多