try块和catch块
1:try块中我们可以放入我们觉得可能抛出异常的代码
2:catch中,我们可以中后面的括号中加入我们想要的异常类型,可以是库里的,也可以是自定义的,只要抛出的异常能转为catch中的异常,那么就会执行其中的代码了;
import java.util.*;
public class exception{
int a=1;
static void ArrayIndexOutOfBoundException() throws myException{
throw new myException("index out bound");
}
public static void main(String[] None){
try{
ArrayIndexOutOfBoundException();
}catch(Exception e){
System.out.print(e);
}
}
}
创建自定义异常
我们不必拘泥与java库中的异常,我们可以自定义匹配我们程序的一个异常,只要我们实现对应的接口,我们就可以像使用库中的异常那样使用我们自己自定义的异常了;
在上面的代码中,我们就实现了对应的Exception接口,该接口是所有exception类的父类,其实现了Throwable接口;
我们可以创建一个接受String类型的异常:
class myException extends Exception{
public myException(String message){
super(message);
}
public String toString(){
return super.getMessage();
}
}
这边当我们new出一个myException的的时候我们就可以输入错误信息了,当我们想要知道知道错误信息是什么的时候就可以知道是啥了;
当然,输出错误信息还有一个方法:printStackTrace(),这个函数很有意思,他会在输出super.getMessage()函数的同时,输出调用栈的轨迹,就如同他的名字一样,看下面的代码:
public class exception{
static void ArrayIndexOutOfBoundException() throws myException{
throw new myException("index out bound");
}
public static void main(String[] None){
try{
ArrayIndexOutOfBoundException();
}catch(Exception e){
e.printStackTrace();
}
}
}
其打印信息:
两个自顶向下地输出从throw到处理异常的调用路径,而且我们看源码:
这个函数内部是调用另外一个printStackTrace的重载,很容易看出来我们将信息输出大标准错误流中;
【这里要注意,一般在工程中不要使用printStackTrace,因为这个方法会将大量的字符串输出,占用内存,最后导致内存不足】;
异常与记录日志
为了记录错误和其他信息,一般我们都会用java内置的logging库;
我们可以写一个自动将错误信息记录到日志中的错误:
class LoggingException extends Exception{
static Logger logger=Logger.getLogger("LoggingException");
public LoggingException(){
StringWriter trace =new StringWriter();//创建一个stringbuffer
PrintWriter print = new PrintWriter(trace);//创建一个printWriter持有trace
printStackTrace(print);//将错误信息存储到trace中
logger.severe(trace.toString());//将错误信息提取出来,然后转化为string传入severe
}
}
这里,String就是对StringBuffer的一个封装;
当我们new出来一个LoggingException对象的时候,调用其构造器,然后在构造器中实现我们的需求,注意,从环境中获取错误信息的操作是中Exception中实现的,在编译的时候,编译器会自动的在子类构造器中插入父类的构造器调用,且是first code,所以我们可以安全地使用printStackTrace函数;
看下面一串代码:
public class exception{
static void ArrayIndexOutOfBoundException() throws LoggingException{
throw new LoggingException("index out bound");
}
public static void main(String[] None){
try{
ArrayIndexOutOfBoundException();
}catch(Exception e){
System.err.println("catch it");
return;
}
}
}
输出:
我们没有在catch语句中加入记录语句,只是做了一个标准性的输出;
我们将错误的记录提前到了ArrayIndexOutOfBoundException()函数中,这给我们带来了一种便利,即当我们不需要重复写一些记录错误信息的代码,因为这在LoggingException的构造器中就做了。
当然,这并不是银弹,当我们的错误信息需要沿着错误信息throw的轨迹更新时,这种方法就不好使了;
栈轨迹
printStackTrace中的错误信息我们可以直接通过getStackTrace方法来获取,在方法返回由栈轨迹构成的数组,其中每一个元素是栈中的一帧,元素0是栈顶元素,即最后一个方法的调用,与之对应,栈底元素是调用序列中的第一个方法,看下面代码:
class LoggingException extends Exception{
static Logger logger=Logger.getLogger("LoggingException");
public LoggingException(String message){
super(message);
StringWriter trace =new StringWriter();//创建一个stringbuffer
PrintWriter print = new PrintWriter(trace);//创建一个printWriter持有trace
printStackTrace(print);//将错误信息存储到trace中
logger.severe(trace.toString());//将错误信息提取出来,然后转化为string传入severe
}
}
public class exception{
static void printException(Exception e){
for (StackTraceElement ele : e.getStackTrace()) {
System.err.println(ele);
}
}
static void g() throws Exception{
throw new Exception();
}
static void f() throws Exception{
g();
}
static void h() throws Exception{
f();
}
public static void main(String[] None){
try{
g();
}catch(Exception e){
printException(e);
}
System.err.println();
try{
f();
}catch(Exception e){
printException(e);;
}
System.err.println();
try{
h();
}catch(Exception e){
printException(e);
}
}
}
输出:
要注意,这里g()的异常会抛到f中,但因为f中没有解决这个异常的环境,所以f接着将异常抛给h,同样的道理,最后抛到main中,由main进行处理;
重新抛出异常:
对于我们已经catch一个异常的时候,我们发现我们不能处理的时候,就将其throw到更高的环境当中处理;
但当一个异常被往更高环境抛的时候,内部的栈轨迹信息不会自动更新,这个需要我们用fillInStackTrace函数来更新;
看下列代码:
public class exception{
static void printException(Exception e){
for (StackTraceElement ele : e.getStackTrace()) {
System.err.println(ele);
}
}
static void g() throws Exception{
throw new Exception();
}
static void f() throws Exception{
try{
g();
}catch(Exception e){
e.fillInStackTrace();
throw e;
}
}
static void h() throws Exception{
g();
}
public static void main(String[] None){
try{
h();
}catch(Exception e){
printException(e);
}
System.err.println();
try{
f();
}catch(Exception e){
printException(e);;
}
System.err.println();
}
}
输出:
啊~~~~~,写完了,学完后面的接着写!