异常 - 已检查和未选中的异常类型

时间:2017-04-05 05:52:38

标签: java exception exception-handling

我有一个关于 java.lang.Exception 的问题以及它在throw / throws子句中的考虑方式。

我有以下两个示例,但我并不完全了解如何处理 java.lang.Exception :作为已检查或未检查的异常。

以下方法成功编译:

public double method1() throws Exception {
   return 0.7;
}
  • 在我看来, java.lang.Exception 受到威胁 java.lang.RuntimeException java.lang.Error 。即使你不处理它,你也可以声明扔掉它。
  • 如果不是Exception,我们使用了一个checked异常(它是 java.lang.Exception 的子类),那么你必须在方法体内有一个throw声明(或者调用抛出已检查异常的方法)。正确?

以下内容无法编译:

private void method2(int age) {
   if (age > 30)
       throw new Exception();
}
  • 这是我的困惑......如果它抛出了类型为 java.lang.RuntimeException java.lang.Error 的子类,它就会编译。
  • 为什么在这种情况下它不会编译?我想这是因为它威胁 java.lang.Exception 作为已检查的异常。但如果是这样,那么为什么method1会编译?

谢谢你, 路易莎

7 个答案:

答案 0 :(得分:2)

  

如果它抛出java.lang.RuntimeException类型的子类或   它会编译的java.lang.Error吗?

是的,RuntimeException未经检查异常(或Error),因此您无需在方法签名或catch明确声明它。比如,例如,NullPointerException,您无法分辨运行时代码中何时可能发生这种情况(即,由于哪个问题,因此,您无需在代码中的任何位置明确处理它),如果由于任何原因在运行时发生,您将看到异常堆栈跟踪。

但是,有一点是,你可以catch(如果你想)RuntimeException(使用catch)并处理它,如果你想在提升时以不同的方式处理事情那个例外,你可以看一下这个。

try {
  //some code
} catch(ArithmeticException exe) {
   //handle it and you can do things differently how you like
}

此外,同样的规则也适用于throws,也就是说,如果您愿意,您可以指定throws ArithmeticException(或任何RuntimeException)方法签名,但它对调用者没有任何影响,相反它会使代码混乱,这不是最佳实践,你可以看一下here。然而,当您在方法中为已检查的Exception指定throws caluse时,则调用者必须处理它,即调用者方法必须使用catch块或throw显式处理它再一次。

  

为什么在这种情况下它不编译?我想这是因为威胁   java.lang.Exception作为已检查的异常。但如果是这样,那么为什么呢   method1编译?

是的,处理已检查的例外有两条规则:

(1)catch使用catch

在方法内部

(2)或throw来自方法(在方法签名中使用throws

即,如果您的代码块throws是一个已检查的exeption,那么您需要在方法中捕获它,否则该方法需要明确声明它会抛出Exception

答案 1 :(得分:2)

在第一种方法1)中,

public double method1() throws Exception 
{
   return 0.7;
}

您正在传播例外 [即Checked Exception]到调用方法,这就是你没有看到编译时异常的原因。 让我告诉你一些可以让你更好理解的东西,

  public void call() {
    method1(); // Because method1() is propagating compile time exception you must need to handle it here. 
  }

  public double method1() throws Exception  {
     return 0.7;
  }

在上面的代码中,call()将得到编译时异常。

在第二种方法中2)

private void method2(int age) {
   if (age > 30)
       throw new Exception(); //I am assuming you forgot to mention new in your code.
}

您正在抛出已检查的异常,因此您必须处理它。 相反,如果您将Exception()更改为RuntimeException,那么您将不会在编译时看到错误。如下,

private void method2(int age) {
       if (age > 30)
           throw new RuntimeException(); // you will not get compile time error.
    }

了解更多详情, http://technostepup.com/CoreJava/ExceptionHandling/exception-types.php

答案 2 :(得分:1)

  

在我看来,java.lang.Exception是威胁java.lang.RuntimeException或java.lang.Error。即使你不处理它,你也可以声明抛出它。

     

如果不使用异常,我们使用了一个已检查的异常(即java.lang.Exception的子类),那么你必须在方法体内有一个throw声明(或调用抛出该方法的方法)例外)。正确?

没有。您可以声明抛出任何异常(已选中或未选中)而不抛出任何异常。

这是有道理的,例如,当在子类中重写该方法并且您希望子类能够抛出已检查的异常时。重写方法只能抛出父类声明的已检查异常。

答案 3 :(得分:0)

该方法需要像编译一样:

private void method2(int age) throws Exception
{
    if (age > 30)
        throw new Exception();
}

但是,经过检查的异常是一种能够对该异常进行操作并执行某些有意义的操作(如释放资源等)的方法,只有当您抛出Exception的实际子类时,您才会知道如何处理该异常。

答案 4 :(得分:0)

在方法2中,您错过了new关键字

throw Exception();

在java中,所有已检查的异常必须使用throws声明声明,并且可能不会声明未选中。

已检查的异常是从java.lang.Excetion类继承的异常。但未经检查的异常会继承java.lang.RuntimeException类。

答案 5 :(得分:0)

Throws子句用于声明异常,thow关键字用于显式抛出异常。 所以当你写

private void method2(int age) {
    if (age > 30)
      throw Exception();
 }

您正在显式抛出异常但未声明该方法可以使用throws子句抛出此异常。

所以正确的代码将是

private void method2(int age) throws Exception {
if (age > 30)
    throw new Exception();
   }

答案 6 :(得分:0)

在你的第一个例子中,如果你调用那个方法,你将不得不处理它抛出的异常,因为它是一个被检查的异常。如果该方法抛出了未经检查的异常,则不需要处理它。

您的第二个示例无法编译,因为您尝试抛出Exception 。你必须抛出它的一个实例。如果在该代码中您只是将Exception更改为RuntimeExceptionError或它们的子类,它仍然无法编译,原因相同。