异常概念
当你不确定一段代码会不会抛出异常时,可以用try把这段代码包起来,用catch区分抛出的宜昌的类型执行对应的操作

通过异常机制,我们可以把异常处理和业务逻辑分离开来,不用使用if-else多重嵌套来折磨自己了。
异常处理运行实例
public class test{
public static void f()
{
int[] a = new int[10];
a[10] = 10; //返回一个ArrayIndexOutOfBoundsException异常
System.out.println("hello_f");
}
public static void g() {
f();
}
public static void h() {
int i=10;
if(i<100) {
g();
}
}
public static void k() {
try {
h();
}
catch(NullPointerException e){
System.out.println("null");
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("hello_k");
throw e; //throw是将异常抛出去,如果没有这一句main中的catch不会被执行
}
}
public static void main(String[] args) {
try {
k();
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("caught");
System.out.println(e.getMessage()); //异常发生时放在异常里面的值【10】
System.out.println(e); //等于e.toString()
System.out.println("main");
e.printStackTrace(); //e.toString的值+异常发生位置
}
}
}
结果:
hello_k
caught
Index 10 out of bounds for length 10
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
main
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
at test.test.f(test.java:7)
at test.test.g(test.java:12)
at test.test.h(test.java:18)
at test.test.k(test.java:24)
at test.test.main(test.java:37)
将"throw e"注释掉的结果:
hello_k
以下是上述代码的命令执行顺序图


异常之间的关系
class FindException extends Throwable{}
class OpenException extends Exception{}//Exception继承自Throwable,其它异常类继承自Exception
class CloseException extends OpenException{} //不合理!
public class test{
public static int open() {
// int[] a = new int[10]; //*当取消注释后a[10]=10会直接抛出异常ArrayIndexOutOfBounds,
// a[10] = 10; //*同时跳过后面的语句[return -1]
return -1;
}
//为以后可能会抛出的异常做准备
public static void readFile() throws OpenException, CloseException, FindException {
if( open() == -1) { //*取消注释后不会判断open的返回值是否等于-1,
throw new CloseException(); //*而是处理a[10]抛出的异常:
} //*将ArrayIndexOutOfBounds返回给调用函数,同时throw这一句也不会执行
}
public static void main(String[] args) {
try {
readFile(); //函数中所有可能抛出的异常都必须有对应的语句
} //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
catch (CloseException e) { //Close必须在Open的前面,因为Close继承自Open,所以如果
System.out.println("Close");//Close在Open下面,就会执行Open对应的catch语句,
} //所以Close永远无法到达。
catch (OpenException e) {
System.out.println("Open");
}
catch (FindException e) {
System.out.println("Find");
}
catch(Exception e) {
System.out.println("Anyaway"); //*因为没有对ArrayIndexOutOfBounds的catch
} //*所以使用Exception来处理
}
}
结果:
Find
取消了注释的结果:
Anyaway
像a[10] = 10这样的运算不用try-catch是因为这些错误太常见了,如果要对应处理,代码会非常庞大。
异常遇到继承
class FindException extends Throwable{}
class OpenException extends Exception{}
class CloseException extends OpenException{}
class ArrayIndex{
public ArrayIndex() throws OpenException{} /*构造函数抛出异常不好*/
public void f() throws OpenException{}
public static void main(String[] args) {}
}
/*如果允许子类的成员抛出超出父类范围的异常,那么代码中父类的成员
不知道如何处理子类抛出的父类没有的异常类型*/
public class test extends ArrayIndex{ //子类的构造函数可以抛出和超出父类异常范围的异常类型
public test() throws OpenException, FindException {
super(); //当父类的构造函数抛出异常时(这不好),子类的构造函数必须也抛出相应异常,
//而默认的构造函数不会抛出异常,所以要手动添加构造函数
}
//定义子类的对象时,对象无从得知父类的构造会抛出什么异常,所以子类的构造必须抛出父类抛出的异常
public void f() throws OpenException{} //成员不可以抛出比父类多的异常
public static void main(String[] args) {//可以抛出比父类少的异常或不抛异常
try {
ArrayIndex p = new test(); //父类中存子类的数据:向下造型
p.f();
} catch (OpenException e) {
e.printStackTrace();
} catch (FindException e) {
e.printStackTrace();
}
}
}
当覆盖一个函数的时候,子类不能声明抛出比父类的版本更多的异常
在子类的构造函数中,必须声明父类可能抛出的全部异常
本文详细讲解了异常处理的概念,通过示例展示了try-catch的运用,讨论了异常之间的继承关系,并强调了在代码中处理常见和特殊异常的技巧。学习如何正确处理OpenException、CloseException和FindException,以及在继承场景下的异常管理策略。

被折叠的 条评论
为什么被折叠?



