java.lang.RuntimeException和java.lang.Exception之间的区别


210

有人请解释之间的差异java.lang.RuntimeExceptionjava.lang.Exception?如果创建自己的异常,如何决定扩展哪个?

Answers:


181

通常,RuntimeExceptions是可以通过编程方式防止的异常。例如 NullPointerExceptionArrayIndexOutOfBoundException。如果null在调用任何方法之前进行检查,则NullPointerException永远不会发生。ArrayIndexOutOfBoundException如果您先检查索引,同样也不会发生。RuntimeException不会由编译器检查,因此它是干净的代码。

编辑:这些天人们喜欢,RuntimeException因为它产生干净的代码。这完全是个人选择。


10
我喜欢“调用者可以避免运行时异常”的观点。这意味着您(作为方法的调用者)应该确保它们甚至不会发生。而已检查的异常是您无法避免的事情,相反,在事后必须对其进行处理。(是的,因为不是每个人都同意检查异常的概念,并且许多人对所有内容都使用RuntimeException,所以这种区分有些混乱了。)
Thilo 2014年

4
如今,人们也喜欢未检查的RuntimeException,因为它与Java 8 Lambda处理兼容,而Exception类型的已检查异常则不兼容。
Hartmut P.

2
我怀疑人们抓住的真正原因RuntimeException是因为它很简单,并且不需要考虑已检查和未检查的异常之间的区别。我认为捕获运行时异常是一个可怕的主意,因为您将捕获不可恢复的异常,例如NullPointerException
多纳尔

186

在Java中,有两种异常类型:已检查的异常和未检查的异常。必须通过代码显式处理已检查的异常,而无需显式处理未检查的异常。

对于已检查的异常,您必须在可能引发异常的代码周围放置try / catch块,或者在方法中添加“ throws”子句,以指示该方法可能会抛出这种类型的异常(必须是在调用类或更高级别中处理)。

从“ Exception”派生的任何异常都是已检查的异常,而从RuntimeException派生的类则未经检查。调用代码不需要显式处理RuntimeExceptions。


3
实际上,“存在两种类型的异常”是正确的,但是为什么Oracle文档说存在三种类型的异常。它将错误视为第三类型。我认为,Error根本不是异常,它只是Throwable(对象),是的,它模仿了运行时异常的行为。您会说些什么?Oracle文档 参考 docs.oracle.com/javase/tutorial/essential/exceptions/…–
Asif Shahzad

3
通常,您并不会使用错误来捕获错误(尽管可能会被捕获),但是您在处理新代码时会使用错误来捕获自己的错误。例如,如果您有一个树if / elseif语句,则最后的else可能确实会抛出Error(“不希望这种情况发生”);。一般而言,异常具有应该发生的用例,而错误没有用例,它们是错误。
丹尼2014年

5
但是开玩笑的是RunTimeException本身扩展了Exception:D(我知道这不会造成任何麻烦,并且JVM会处理整个上下文)
Alireza Mohamadi

94

在查看java.lang.RuntimeExceptionjava.lang.Exception类之间的区别之前,您必须了解Exception层次结构。两个ExceptionError类都从类衍生的Throwable(其从类派生Object)。该类RuntimeException是从class派生的Exception

所有异常均源自ExceptionRuntimeException

所有派生自的异常RuntimeException都称为未经检查的异常。并且所有其他异常均为检查异常。必须在代码中的某个地方捕获已检查的异常,否则它将无法编译。这就是为什么它们被称为检查异常。另一方面,对于未经检查的异常,调用方法没有义务处理或声明它。

因此,编译器强制您处理的所有异常均直接源自,编译器强制您处理的java.lang.Exception所有其他异常均源自java.lang.RuntimeException

以下是RuntimeException的一些直接已知的子类。

AnnotationTypeMismatchException,
ArithmeticException,
ArrayStoreException,
BufferOverflowException,
BufferUnderflowException,
CannotRedoException,
CannotUndoException,
ClassCastException,
CMMException,
ConcurrentModificationException,
DataBindingException,
DOMException,
EmptyStackException,
EnumConstantNotPresentException,
EventException,
IllegalArgumentException,
IllegalMonitorStateException,
IllegalPathStateException,
IllegalStateException,
ImagingOpException,
IncompleteAnnotationException,
IndexOutOfBoundsException,
JMRuntimeException,
LSException,
MalformedParameterizedTypeException,
MirroredTypeException,
MirroredTypesException,
MissingResourceException,
NegativeArraySizeException,
NoSuchElementException,
NoSuchMechanismException,
NullPointerException,
ProfileDataException,
ProviderException,
RasterFormatException,
RejectedExecutionException,
SecurityException,
SystemException,
TypeConstraintException,
TypeNotPresentException,
UndeclaredThrowableException,
UnknownAnnotationValueException,
UnknownElementException,
UnknownTypeException,
UnmodifiableSetException,
UnsupportedOperationException,
WebServiceException 

47

检查Exception,并取消选中RuntimeException。

Checked表示编译器要求您在catch中处理异常,或将您的方法声明为抛出该异常(或其超类之一)。

通常,如果期望API的调用者处理该异常,则引发一个检查的异常;如果调用者通常无法处理的异常,则引发一个非检查的异常,例如,参数之一即程序错误错误。


15

运行时异常类(RuntimeException及其子类)免于编译时检查,因为编译器无法确定不会发生运行时异常。(来自JLS)。

在您设计的类中,应将Exception子类化,并抛出其实例以发出任何异常情况的信号。这样做,您将明确向类的客户端发出信号,告知您使用类可能会引发异常,并且他们必须采取措施来处理这些特殊情况。

下面的代码段解释了这一点:

//Create your own exception class subclassing from Exception
class MyException extends Exception {
    public MyException(final String message) {
        super(message);
    }
}

public class Process {
    public void execute() {
        throw new RuntimeException("Runtime");
    }  
    public void process() throws MyException {
        throw new MyException("Checked");
    }
}

在以上Process类的类定义中,方法execute可以引发RuntimeException,但方法声明不需要指定它引发RuntimeException

该方法process将引发一个已检查的异常,并且应该声明它将抛出一个MyException类型的已检查的异常,否则将引发编译错误。

上面的类定义也会影响使用Process类的代码。

该调用new Process().execute()是有效的调用,其中,形式调用 new Process().process()给出编译错误。这是因为客户端代码应采取步骤进行处理MyException(例如,可以将try(catch)块中包含对process()的调用)。


13

正确使用RuntimeException?

来自未经检查的异常-争议

如果可以合理预期客户端会从异常中恢复,请将其设置为已检查的异常。如果客户端无法采取任何措施来从异常中恢复,请将其设置为未经检查的异常。

请注意,未检查的异常是从派生的,RuntimeException而检查的异常是从派生的Exception

RuntimeException如果客户端无法采取任何措施从异常中恢复,为什么还要抛出a ?本文介绍:

运行时异常表示由编程问题引起的问题,因此,无法合理地期望API客户端代码从它们中恢复或以任何方式进行处理。这些问题包括算术异常,例如被零除;指针异常,例如尝试通过空引用访问对象;以及索引异常,例如尝试通过太大或太小的索引访问数组元素。


5

从oracle文档中:

这是底线准则:如果可以合理地预期客户端将从异常中恢复,则将其设置为已检查的异常。如果客户端无法采取任何措施来从异常中恢复,请将其设置为未经检查的异常。

运行时异常表示由编程问题导致的问题,因此,无法合理地期望API客户端代码从它们中恢复或以任何方式进行处理。

RuntimeExceptions类似于runtimeException的“通过无效使用api引起的异常”示例:IllegalStateException,NegativeArraySizeException,NullpointerException

使用“例外”,您必须明确地捕获它,因为您仍然可以做一些事情来恢复。异常示例包括:IOException,TimeoutException,PrintException ...


4

简而言之,如果您的客户端/用户可以从Exception中恢复,则将其设置为Checked Exception,如果您的客户端无法采取任何措施来从Exception中恢复,则将其设置为Unchecked RuntimeException。例如,RuntimeException将是一个编程错误,例如被零除,除了程序员本人之外,任何用户都不能对此进行任何操作,那么它就是RuntimeException


3

RuntimeException是Exception类的子类

这是Exception类的许多子类之一。RuntimeException是在Java虚拟机的正常操作期间可能引发的那些异常的超类。方法不需要在其throws子句中声明RuntimeException的任何子类,这些子类在方法执行期间可能会抛出但未被捕获。

该层次是

java.lang.Object

--- java.lang.Throwable

------- java.lang.Exception

------------- java.lang.RuntimeException


0

异常是处理应用程序流程中意外事件的好方法。编译器未选中RuntimeException,但您可能希望使用扩展Exception Class的Exceptions来控制api客户端的行为,因为它们需要捕获错误才能进行编译。还形成了良好的文档。

如果要实现干净的接口,请使用继承对应用程序具有的不同类型的异常进行子类化,然后公开父异常。


0

有两种类型的异常,如果您收到此类异常,则可以从检查的异常中恢复。运行时异常是无法恢复的,运行时异常是编程错误,程序员在编写代码时应注意这一点,继续执行此操作可能会导致错误的结果。运行时异常与违反前提条件ex有关。您有一个大小为10的数组,并且您尝试访问第11个元素,它将抛出ArrayIndexOutOfBoundException


0
  1. 用户定义的异常可以是Checked Exception或Unchecked Exception,这取决于扩展到的类。

  2. 如果用户定义的异常扩展到Exception类,则可以是Custom Checked Exception。

  3. 如果用户定义的异常扩展到“运行时异常”类,则可以是“自定义未经检查的异常”。

  4. 定义一个类并使其成为Exception或Runtime Exception的子级

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.