程序中,不存在所谓的“异常”,只存在错误,错误会导致我们的程序在运行期无法继续运行。那么什么是异常?
异常
是Java为了解决在出现问题
时发出的一个通知,这个通知到达它该到达的地方,然后在这个地方得到解决,然后使程序继续向错误发生时的情况运行。
整体结构:
Error: Error用来表示编译时和系统错误,一般我们不用关心; 而异常是发生错误时被抛出的一个通知,所以Error是在编译时和系统错误时被抛出的异常。
Exception:当异常抛出时,说明了我们程序出现了问题,我们需要处理这些问题。Exception又分为不检查异常
和检查异常。
(1)不检查异常
当有方法会抛出RuntimeException类型的异常时(系统自动抛出),我们不需要去捕获它(try-catch),所以这类异常被称为不检查异常
。 RuntimeException类型的异常不用我们去捕获,因此我们在Code的时候一定要注意防止RuntimeException的发生。
注意:不被检查的异常编译时不会强制让我们捕获,所以需要大家自己注意这些异常。
(2)检查异常
这一类异常抛出时,我们必须去捕获它,如SQLException、XMLStreamException等异常。
——————————————————————————————————————————————————————————————————————
在某个函数方法内抛出异常或在函数内调用其他方法抛出异常,该方法将终止。所以为了程序继续运行下去,可以在方法内设置一个特殊的块来捕获异常,即try,也称为 监控区域。 此处可以参考博客:try catch里面try catch嵌套
抛出的异常需要在某处得到处理,这个“地点”就是异常处理程序。
try {
// Code that might generate exceptions
} catch(Type1 t1){
// Handle exceptions of type1
} catch(Type2 t2){
// Handle exceptions of type2
} catch(Type3 t3){
// Handle exceptions of type3
}
当发生异常事时(监控区域抛出异常),Java异常处理机制将负责搜寻catch中与异常类型相匹配的第一个处理程序,进入这个catch块,也就是说只有匹配的catch字句才能执行,即便是下面还有匹配的类型也不会执行,具有唯一匹配性。
(3)finally :无论try中是否抛出异常,它们都能得到执行,这就是finally字句
的作用。即便是你在try或catch中加入了continue、break或者return。Java中主要通过finally把资源恢复到它们的初始状态。
————————————————————————————————————————————————————————————————
终止模式/恢复模式
Java对于异常的处理采取的是终止模式
,一旦发生问题,程序将不能继续执行,与之对应的是恢复模式
,就是当异常抛出时,程序能够继续执行,而不是终止。
异常说明 :属于方法说明的一部分,紧跟在参数列表之后。
void method() throws IOException{
//…………
}
如果某个方法有了异常说明,我们在使用的时候就必须捕获它,即使可能该方法根本不可能真实的抛出过该异常。
继承的方法说明
当某个子类继承父类时,如果父类中某个方法(public或者protected)有异常说明,子类在覆盖方法时,异常说明只能是父类的一样的异常说明或者无异常说明,不能添加父类方法没有的异常说明。还有一个特殊情况,一个类的父类方法和接口方法同名,而且都添加了异常说明,这种情况下的方法不能添加任何异常说明。
class A {
void a() throws XPathException {
}
}
interface B {
void a() throws DataFormatException;
}
class AB extends A implements B {
@Override
public void a() {}
// public void a() throws XPathException {} 不能编译
}
JavaTM Platform Standard Edition 6 API 规范
举例:
public class Test {
public static void main(String[] args) {
try {
throw new Exception("My Exception");
} catch (Exception ex) {
System.out.println("getMessage(): " + ex.getMessage());
System.out.println("getLocalizedMessage(): " + ex.getLocalizedMessage());
System.out.println("toString(): " + ex.toString());
System.out.println("printStackTrace(): ");
ex.printStackTrace(System.out);
}
}
}/* Output:
getMessage(): My Exception
getLocalizedMessage(): My Exception
toString(): java.lang.Exception: My Exception
printStackTrace():
java.lang.Exception: My Exception
at com.exercise.Test.main(Test.java:13)
*/
说明:getLocalizedMessage()和getMessage()获取的都是使用了带有参数的构造方法传入的信息,如上列为“My Exception”。toString()方法包含了getMessage()方法的信息,printStackTrace()方法则包含了toString()方法的内容,printStackTrace()方法打印的的是此异常调用栈的轨迹,显示了把你带到异常抛出点的方法调用序列,可以根据类名和行号具体定位。
栈轨迹
printStackTrace()提供的信息可以通过getStackTrace()方法获取到更详细的内容,该方法将返回一个数组,由栈轨迹元素(StackTraceElement)构成,每个元素表示栈中的一桢,元素0是栈顶元素,是方法调用序列中最后一个方法调用,也就是在这个方法中创建或抛出了异常。数组中最后一个元素(栈底)是调用序列中的第一个方法调用。
public class Test {
static void methodOne() {
try {
throw new Exception();
} catch (Exception e) {
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
System.out.println(stackTraceElement.getMethodName());
}
}
}
static void methodTwo() {
methodOne();
}
static void methodThree() {
methodTwo();
}
public static void main(String[] args) {
methodOne();
System.out.println("------------分割线------------");
methodTwo();
System.out.println("------------分割线------------");
methodThree();
}
}/* Output:
methodOne
main
------------分割线------------
methodOne
methodTwo
main
------------分割线------------
methodOne
methodTwo
methodThree
main
*/
此例只打印了方法名,还可以通过StackTraceElement打印更多的信息。
参考: