java之异常处理


JAVA的基本理念是“结构不佳的代码不能运行” 找到程序错误的最佳时机是运行程序之前,可惜的是在编译期间并不能找出所有的错误,有些错误必定要在 运行期找出。而这就需要错误源能通过某种方式,把错误的信息传递给某一个接收者,这个接受者会正确处理这个问题,若该接收者无法处理,则他可以把错误的信息传给下一个接收者(一个更大的环境)。

异常的概念:

异常就是在程序运行期出现的错误。(如,除以0、数组下标越界)

java异常处理机制 是 java提供的用于处理程序中错误的一种 方法。

异常情形是指阻止当前方法或作用域继续执行的 问题。(注意,普通问题是指总是可以利用当前环境下能够得到的足够信息来解决的问题,而异常情形 是指在当下的环境中无法获得必要的信息来解决的问题。)

public class Test {
	public static void main (String [] args) {
		int arr [] = {0,1,2,3};
		System.out.print(arr[5]);
	}
}

可以发现输出语句中 数组的下标越界,但javac时(编译期间)没有错误,结果运行时出现异常:
在这里插入图片描述

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
 Index 5 out of bounds for length 4
        at Test.main(Test.java:4)

表示为:运行期间在“main”线程中出的错,代码的第4行出现了数组下标越界的异常。
.ArrayIndexOutOfBoundsException 为错误的名字
java.lang.ArrayIndexOutOfBoundsException: 表示了这个错误在lang包的Exception类。

从这里也可以看出java 把 exception异常看为某一个类的一个对象

让我们在api文档中看一看。在这里插入图片描述

设计良好的程序应该在异常发生时提供处理这些错误的方法,使得程序不会因为异常的发生而阻断或产生不可以预见的错误。

抛出异常:在程序de运行期间如出现异常情形,可以生成一个异常类对象,该异常类对象封装了异常情形的信息,把这个信息提交给java运行时系统(接收者)的过程称为抛出(throw)异常。

java运行时系统默认的处理 如上图,直接把异常对象里面包装的信息打印到了控制台上。

而我们要做的一点就是,在抛给java运行时系统之前,我们把异常给捕捉住,并作出相应的处理。

捕获异常

java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获异常。

我们需要理解**监控区域:**的概念,是一段可能出现异常的代码,其后紧跟着解决异常的 代码。

try{…}catch{…}finally{…}

try块
如果希望方法内部出现异常或者方法内部调用的其他方法出现异常的程序继续运行的话,则需要设置一个try块,在这个try块里尝试各种可能引发异常的方法调用,用来捕捉异常。

try{
监控区域
}

当然捕捉到异常之后,就是对异常的处理。
异常处理紧跟在try块之后,用catch来表示,为异常处理程序


try {
	......
}catch(Type1 id1) {
	// handle exceptions of Type1
}catch(Type2 id3) {
	// handle exceptions of Type2
}catch(Type3 id3) {
	// handle exceptions of Type3
}......

每一个catch子句,看起来就像是仅仅接受一个特殊参数的方法。

当异常被抛出时,异常处理机制将负责搜寻这个特殊参数与异常类型相匹配的第一个处理程序(当某一个异常对象发生了,异常对象封装到了参数对象中,之后调用catch),然后进入catch子句,这个时候认为异常得到了处理。catch子句结束则处理程序的查找过程结束。

在这里插入图片描述

public class Test {
	public static void main (String [] args) {
		int arr [] = {0,1,2,3};
		try {
		System.out.print(arr[6]);
	}catch (ArrayIndexOutOfBoundsException id1) {//参数id1 为我们给异常对象取的名字
		System.out.println("xi tong cuo wu qing chong shi");
		id1.printStackTrace();//该方法稍后会说,在此知道它利于调试,可以打印出错误的 堆栈信息 即可。
	}
	}
}


运行结果:

xi tong cuo wu qing chong shi
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
        at Test.main(Test.java:5)

在这里插入图片描述

finally{ }

  • finally 的代码无论是否产生异常都会执行
  • finally语句为异常提供一个同一的出口,使得在控制流程转到程序其他部分以前、能够对程序的状态作同一的管理。
  • 通常利用finally语句中进行清理工作
    • 关闭打开的文件…
    • 删除临时文件…

throw和throws

throw:用在方法内,用来抛出一个异常对象,并结束当前方法的执行。
如:throw new xxxException(“ ”)

throws:用在 方法声明处 声明异常
调用了一个声明抛出异常的方法,我们就必须处理声明的异常,要么继续使用 throws声明抛出,最终交给jvm,要么try…catch自己 处理异常。

异常处理

try{…}catch{…}finally{…}

捕获所有异常

catch (Exception e ) {
  System.out.println (" Caught an exception ")
}

这将会捕获所有异常,所以最好将其放在捕获列表的尾部。
相关的方法
用来获取详细信息,或用本地语言表示的详细信息。
String getMessage();
String getLocalizedMessage();

返回对Throwable的简单描述。
String toString();

打印Throwable和其调用栈轨迹。
void printStackTrace()
void printStackTrace(PrintSteam)
void printStackTrace(java.io.PrintWriter)

返回一个表示此对象类型的的对象
getClass()
使用getName()查询这个对象包含 包的信息名称
使用getSimpleName()查询这个对象类的名称。

代码举例:

public class ExceptionM {
	public static void main (String [] args) {
		try {
			throw new Exception ("My Exception");
		}catch (Exception e ) {
			System.out.println("Caught Exception");
			System.out.println("getMessage():"+ e.getMessage());
			System.out.println("getLocalizedMessage():"+ e.getLocalizedMessage());
			System.out.println("toString():"+ e);
			System.out.println("printStackTrace():");
			e.printStackTrace(System.out);
		}
	}
}

运行结果:
在这里插入图片描述

Caught Exception
getMessage():My Exception
getLocalizedMessage():My Exception
toString():java.lang.Exception: My Exception
printStackTrace():
java.lang.Exception: My Exception
        at ExceptionM.main(ExceptionM.java:4)

注*:可以发现上诉方法每一个都是它们前一个的超集。

抛给上一级环境
将捕获到的异常重新抛出,抛给一个更大的环境去处理,需要注意的是,这个时候同一个try块的后续子句将被忽略。

例如1:


try {
	.........
}catch (Exception e ) {
	System.out.println("An exception was thrown");
	throw e;//重新抛出异常
}
public class Test2 {
	public static void main(String [] args) {
		Test2 test = new  Test2 ();
		try {
			test.m1();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void m1() throws Exception {
		m2();
	}
	
	public void m2() throws Exception {
		m3();
	}
	
	public void m3() throws Exception {
		throw new Exception("Exception occur in m3!");
	}
}

运行结果:

java.lang.Exception: Exception occur in m3!
        at Test2.m3(Test2.java:20)
        at Test2.m2(Test2.java:16)
        at Test2.m1(Test2.java:12)
        at Test2.main(Test2.java:5)

若一直抛,最终会抛给jvm,jvm打印出堆栈信息。

注意: 重写与异常的关系
若有重写方法抛出异常 则要与被重写方法抛出异常一样,或不抛出异常

异常的分类

在前面 我们提到 java 把 exception异常看为某一个类的一个对象

而jdk中定义了很多异常类,这些类对应了各种各样可能出现的异常情形。

异常类的根类为 Throwable(万恶之源),其能够用来表示任何可以作为异常被抛出的类。Throwable直接子类有 Error 和 Exception 。

见图:

在这里插入图片描述
Error:编译时和系统错误。一般情况不用管
Exception:我们可以处理的异常,但是没必要
RuntimeException:一种特殊的异常,经常出现的错误,可以处理,但没必要。
除 RuntimeException 之外 Exception中 api 文档里面注明会有异常抛出的就必须得捕捉。

所以要注意对api文档的查阅。

自定义异常类

因为java中提供的异常类不可能预料所有的错误,所以我们可以自己定义异常类来表示程序可能会遇到的各种程序问题。

定义自己异常类,必须从已有的异常类继承

让编译器产生默认构造器:

// 自定义了一个SimpleException类
//编译器将会自动创建默认的构造器,之后会调用基类的默认构造器(构造方法)
class SimpleException extends Exception { }

public class SimpleE {
// 利用throws 声明该方法会产生SimpleException异常
	public void f () throws SimpleException{
		System.out.println("Throw SimpleException from f()");
		//声明了异常 就必须要抛出
		throw new SimpleException();
	}
	public static void main(String[] args) {
		SimpleE test = new SimpleE ();
		// 捕捉并处理异常
		try {
			test.f();
		}catch (SimpleException e) {
			System.out.println("Caught it !");
		}
	}
}

运行结果:

Throw SimpleException from f()
Caught it !

当然也可以为异常类定义一个带参数的构造器,只不过这个时候,一定要记得调用基类的带参构造器


class SimpleException2 extends Exception { 
	public  SimpleException2() { }
	public  SimpleException2(String msg) {
		super(msg);
	}
}
.........
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值