异常本质上是程序上的错误,包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等. 错误在我们编写程序的过程中会经常发生,包括
编译期间和运行期间的错误
,在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,并且运行期间的错误往往是难以预料的。假若程序在运行期间出现了错误,如果置之不理,程序便会终止或直接导致系统崩溃
检查性异常(checked exceptions): 必须在在方法的 throws 子句中声明的异常
。它们扩展了异常,旨在成为一种“在你面前”的异常类型。JAVA希望你能够处理它们,因为它们以某种方式依赖于程序之外的外部因素。检查的异常表示在正常系统操作期间可能发生的预期问题。当你尝试通过网络或文件系统使用外部系统时,通常会发生这些异常。大多数情况下,对检查性异常的正确响应应该是稍后重试,或者提示用户修改其输入。
非检查性异常(unchecked Exceptions) 是不需要在throws子句中声明的异常。由于程序错误,JVM并不会强制你处理它们,因为它们大多数是在运行时生成的。它们扩展了 RuntimeException
。最常见的例子是 NullPointerException, 未经检查的异常可能不应该重试,正确的操作通常应该是什么都不做,并让它从你的方法和执行堆栈中出来。
错误(errors) 是严重的运行时环境问题,肯定无法恢复。例如 OutOfMemoryError,LinkageError 和 StackOverflowError,通常会让程序崩溃。
//在 methodD 方法中若出现某些不正常的情况可能会触发 XxxException 或 YyyException 异常。
public void methodD() throws XxxException, YyyException {// 方法体抛出XxxException和YyyException异常
}
//注意, 方法体内使用 throw 进行抛出, 方法外使用throws
public void methodD() throws XxxException, YyyException { // 方法签名// 方法体......// 出现XxxException异常if ( ... )throw new XxxException(...); // 构造一个XxxException对象并抛给JVM...// 出现YyyException异常if ( ... )throw new YyyException(...); // 构造一个YyyException对象并抛给JVM...
}
try{//可能会抛出异常的代码
}
catch(Type1 id1){//处理Type1类型异常的代码
}
catch(Type2 id2){//处理Type2类型异常的代码
}
finally{//总是会执行的代码
}
如果 methodD 方法抛出 XxxException 或 YyyException,则 JVM 将终止 methodD 方法和methodC 方法并将异常对象沿调用堆栈传递给 methodC 方法的调用者。
public void methodC() throws XxxException, YyyException { // 让更高层级的方法来处理...// 调用声明XxxException和YyyException异常的methodD方法methodD(); // 无需使用try-catch...
}
//破坏了检查性异常的目的
catch (NoSuchMethodException e) { return null;
}
try { someMethod();
} catch (Exception e) { //错误方式 LOGGER.error("method has failed", e);
}
public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("沉默王二.txt")) {}catch (IOException e) {e.printStackTrace(); //错误案例throw e;}
}
延迟捕获异常,让程序在第一个异常捕获后就终止执行。