简体   繁体   English

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

[英]Exception - checked and unchecked exception type

I have a question regarding java.lang.Exception and the way it is considered within the throw/throws clauses. 我对java.lang.Exception及其在throw / throws子句中的考虑方式有疑问。

I have the following 2 examples and I don't understand exactly how the java.lang.Exception is handled: as checked or unchecked exception. 我有以下两个示例,但我不完全了解java.lang.Exception是如何处理的:作为检查还是未检查的异常。

The following method compiles successfully: 以下方法成功编译:

public double method1() throws Exception {
   return 0.7;
}
  • here it seems to me that the java.lang.Exception is threaten java.lang.RuntimeException or java.lang.Error . 在我看来, java.lang.Exception受到威胁java.lang.RuntimeExceptionjava.lang.Error You can declare to throw it even if you don't handle it. 即使您不处理它,也可以声明将其抛出。
  • if instead of an Exception we used a checked exception (that are sub-classes of java.lang.Exception ) then you should had to have a throw declaration within the body of the method (or call a method that throws that checked exception). 如果不是使用Exception而是使用检查的异常(属于java.lang.Exception的子类),则您必须在方法的主体内具有throw声明(或调用引发该检查的异常的方法)。 Right? 对?

The following doesn't compile: 以下内容无法编译:

private void method2(int age) {
   if (age > 30)
       throw new Exception();
}
  • here is my confusion...if it was throwing a subclass of type java.lang.RuntimeException or java.lang.Error it would had compiled. 这是我的困惑...如果它抛出了本应编译的java.lang.RuntimeExceptionjava.lang.Error类型的子类。
  • why in this case it doesn't compile ? 为什么在这种情况下无法编译? I guess it is because it threats java.lang.Exception as a checked exception. 我猜是因为它威胁java.lang.Exception作为已检查的异常。 But if it is so, then why method1 does compile? 但是如果是这样,那么method1为什么要编译?

Thank you, Luisa 谢谢你,路易莎

If it was throwing a subclass of type java.lang.RuntimeException or java.lang.Error it would had compiled? 如果它抛出java.lang.RuntimeException或java.lang.Error类型的子类,它将进行编译吗?

Yes, RuntimeException is unchecked Exception (or Error ), so you don't need to declare it on the method signature or catch it explicitly. 是的, RuntimeException是未经检查的Exception(或Error ),因此您无需在方法签名上声明它或显式catch它。 Like, for example, NullPointerException , you can't tell when that might happen in the code at Runtime (ie., because of which issue, so, you don't need to explicitly deal with it everywhere inside the code), if it happens at runtime because of any reason, you will see the exception stacktrace. 例如,类似于NullPointerException ,您无法确定在运行时代码中何时会发生这种情况(即,由于哪个问题,因此,您无需在代码内部的任何地方显式处理它)。由于任何原因在运行时发生,您将看到异常stacktrace。

But, one point is that, you can catch (if you want) RuntimeException (using catch ) and handle it, if you wanted to deal with the things differently upon raising that exception, you can look below on this. 但是,有一点是,您可以catch (如果需要) RuntimeException (使用catch )并对其进行处理,如果您想在引发该异常时以不同的方式处理事情,则可以在下面进行查看。

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

Also, the same rule applies even for throws as well, ie, if you wanted to, you can specify the throws ArithmeticException (or any RuntimeException ) on the method signature, but it does not make any difference to the caller, rather it will clutter the code and it is NOT the best practice, you can look here on this. 同样,该规则甚至也适用于throws ,即,如果您愿意,您可以在方法签名上指定throws ArithmeticException (或任何RuntimeException ),但是它对调用方没有任何影响,而是会造成混乱代码,但这不是最佳实践,您可以在此处查看。 Whereas when you specify the throws caluse on the method for checked Exception, then the caller is forced to deal with it ie, the caller method has to explicitly handle it using catch block or throw it again. 而当您在用于检查的Exception的方法上指定throws Caluse时,则调用者被迫处理它,即,调用者方法必须使用catch块显式处理它或再次throw它。

why in this case it doesn't compile? 为什么在这种情况下无法编译? I guess it is because it threats java.lang.Exception as a checked exception. 我猜是因为它威胁java.lang.Exception作为已检查的异常。 But if it is so, then why method1 does compile? 但是如果是这样,那么method1为什么要编译?

Yes, there are two rules for dealing with checked Exceptions: 是的,有两个规则可以处理检查的异常:

(1) catch it inside the method using a catch block (1) catch它的方法内使用catch

(2) or throw it from the method (using throws in the method signature) (2)或从方法中throw它(在方法签名中使用throws

ie, If your code block throws a checked exeption then either you need to catch it inside the method or else the method needs to explicitly declare that it throws that Exception . 即,如果您的代码块throws了被检查的throws ,那么您要么需要将其捕获到方法内部,要么方法需要显式声明它抛出了Exception

In first method 1), 在第一种方法1)中,

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

you are propagating Exception [ie Checked Exception] to the calling method that is why you are not seeing compile time exception. 您正在将异常 [即检查异常]传播到调用方法,这就是为什么您没有看到编译时异常的原因。 let me show you something which can make you understand better, 让我向您展示一些可以使您更好地理解的东西,

  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;
  }

In above code, call() you will get compile time exception. 在上面的代码中,call()将获得编译时异常。

In the second method 2) 在第二种方法2)

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

you are throwing checked exception so you must need to handle it. 您将抛出检查异常,因此您必须要处理它。 If instead you will change Exception() to RuntimeException so you will not see error at compile time. 相反,如果将Exception()更改为RuntimeException,则在编译时不会看到错误。 like below, 像下面一样

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

for more details, http://technostepup.com/CoreJava/ExceptionHandling/exception-types.php 有关更多详细信息,请访问http://technostepup.com/CoreJava/ExceptionHandling/exception-types.php

here it seems to me that the java.lang.Exception is threaten java.lang.RuntimeException or java.lang.Error. 在我看来,java.lang.Exception受到威胁java.lang.RuntimeException或java.lang.Error。 You can declare to throw it even if you don't handle it. 即使您不处理它,也可以声明将其抛出。

if instead of an Exception we used a checked exception (that are sub-classes of java.lang.Exception) then you should had to have a throw declaration within the body of the method (or call a method that throws that checked exception). 如果不是使用Exception而是使用检查的异常(属于java.lang.Exception的子类),则您必须在方法的主体内具有throw声明(或调用引发该检查的异常的方法)。 Right? 对?

No. You can declare you throw any exception (checked or unchecked) and not throw any. 不可以。您可以声明抛出任何异常(选中或未选中),并且不抛出任何异常。

This makes sense for example when the method is overridden in a subclass and you want the subclass to be able to throw checked exceptions. 例如,当方法在子类中被重写并且您希望子类能够引发检查的异常时,这是有意义的。 Overriding methods can throw only the checked exceptions the parent class declares. 重写方法只能抛出父类声明的检查异常。

The method needs to be like this for compilation : 该方法需要像这样进行编译:

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

However, checked exceptions are a way of being able to act on that exception and do something meaningful such as freeing up resources etc and you will know what to do with that exception only when you throw actual subclass of Exception. 但是,检查异常是一种能够对该异常执行操作并执行有意义的操作(如释放资源)的方式,只有当您抛出Exception的实际子类时,您才知道该异常的处理方法。

In method2 you miss new keyword at line 在method2中,您错过了第一个new关键字

throw Exception();

In java all checked exceptions must be declared with throws declaration and unchecked may not be declared. 在Java中,必须使用throws声明声明所有已检查的异常,并且不能声明未检查的异常。

Checked exceptions are those inherited from java.lang.Excetion class. 检查的异常是从java.lang.Excetion类继承的异常。 But unchecked exceptions inherit java.lang.RuntimeException class. 但是未经检查的异常会继承java.lang.RuntimeException类。

Throws clause in used to declare an exception and thow keyword is used to throw an exception explicitly. Throws子句用于声明异常,thow关键字用于显式抛出异常。 So when you write 所以当你写

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

You are throwing an exception explicitly but not declaring that the method can throw this exception using throws clause. 您正在显式引发一个异常,但没有声明该方法可以使用throws子句引发该异常。

So the correct code will be 所以正确的代码将是

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

In your first example, if you call that method you will have to handle the exception it throws, because it's a checked one. 在第一个示例中,如果调用该方法,则必须处理它引发的异常,因为它是已检查的异常。 If the method threw an unchecked exception you would not need to handle it. 如果该方法引发了未经检查的异常,则无需处理它。

Your second example does not compile because you are trying to throw the Exception class . 您的第二个示例未编译,因为您尝试抛出Exception You must throw an instance of it instead. 您必须改为抛出它的一个实例。 If in that code you just change Exception to RuntimeException or Error or a subclass of them it would still not compile, for the same reason. 如果出于同样的原因,如果在该代码中仅将Exception更改为RuntimeExceptionError或它们的子类,则仍然无法编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM