try-catch语法和异常详解

两种语法介绍

我们以前使用的try-catch格式是这样的
格式如下:

// 申请资源对象需要外置定义
try{
	//1. 申请资源和要执行的代码逻辑
}catch(IOException e){
	//2. 捕获到的异常
	e.printStackTrace();
}finally{
	//3. 关闭资源,无论如何在最后都会执行到的代码
}

例子:

InputStream in=null;
OutputStream out=null;
try{
	in=new FileInputStream("D:\\demo1.txt");
	out=new FileOutputStream("D:\\demo2.txt");
	byte[] buf=new byte[1024];
	int len=0;
	while((len=fis.read(buf))!=-1){
		System.out.println(new String(buf,0,len));
		out.write(buf,0,len);
	}
}catch(Exception e){
	e.printStackTrace();
}finally{
	try{
		if(in!=null){
			in.close();
		}
		if(out!=null){
			out.close();
		}
	}catch(Exception e){
		e.printStackTrace();
	}
}

现在有jdk1.7新特性的书写方式:try-with-resource,可以实现自动关流操作
格式如下:

try(
	//1.对资源的申请
	InputStream in=new FileInputStream("D:\\demo1.txt");
	OutputStream out=new FileOutputStream("D:\\demo2.txt");	
){
	//2.执行的代码
}catch(Exception e){
	//3.捕获到的异常
	e.printStackTrace();
}

注:
1. 无论在 2 处执行时是否出现异常(如果出现异常被 3 捕获)1 处都会自动关流。
2. 关流的顺序是按照创建资源的逆顺序自动关闭。
3. 这样就不用再写一堆finally中的代码了,这在InputStream和OutputStream中很好用。
4. 只要实现了AutoCloseable接口的流都可以实现这种操作。

public abstract class InputStream implements Closeable {
public interface Closeable extends AutoCloseable {
//@since 1.7
public interface AutoCloseable {

例子:

try(
	InputStream in=new FileInputStream("D:\\demo1.txt");
	OutputStream out=new FileOutputStream("D:\\demo2.txt");
){
	byte[] buf=new byte[1024];
	int len=0;
	while((len=in.read(buf))!=-1){
		System.out.println(new String(buf,0,len));
		out.write(buf,0,len);
	}
}catch(Exception e){
	e.printStackTrace();
}

执行顺序:

// 申请资源对象需要外置定义
int a=0;
	try{
		//1. 申请资源和要执行的代码逻辑
		//a=1/0;
		a=6;
		return a;
	}catch(Exception e){
		//2. 捕获到的异常
		e.printStackTrace();
		a=7;
	}finally{
		//3. 关闭资源,无论如何在最后都会执行到的代码
		return a=8;
	}

注:

  1. 没有出现异常时:1->3
    其实是在1中return时会将a设置一个标记值6,然后向后检查是否有finally,然后执行finally中的逻辑,将a设置为8,最后在3中返回a=8;
    详解:
    在不抛出异常的情况下,程序执行完 try 里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块,
    如果没有 finally 代码块,整个方法在执行完 try 代码块后返回相应的值来结束整个方法;
    如果有 finally 代码块,此时程序执行到 try 代码块里的 return 语句之时并不会立即执行 return,而是先去执行 finally 代码块里的代码,
    若 finally 代码块里没有 return 或没有能够终止程序的代码,程序将在执行完 finally 代码块代码之后再返回 try 代码块执行 return 语句来结束整个方法;
    若 finally 代码块里有 return 或含有能够终止程序的代码,方法将在执行完 finally 之后被结束,不再跳回 try 代码块执行 return。
  2. 出现异常时:1->2->3。

try-catch中的异常处理

异常发生的原因很多,通常有以下几类

  1. 用户输入了非法数据。
  2. 网络通信中断,JVM内存溢出。
  3. 要打开的文件不存在。

在try-catch代码块放在异常可能发生的地方,在里面的代码称为保护代码
一个try代码块后跟多个catch代码块,叫多重捕获。

如果一个方法捕获一个检查性异常,那么该方法必须使用throws关键字在方法签名的尾部来声明。
也可以使用throw关键字抛出一个异常,无论是新实例化还是刚捕获到的。

例如:

public static void main(String[] args) throws Exception{
		try{
			int s=test01();
			System.out.println(s);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
public static int test01() throws Exception{
	int s= 0;
	try{
		s=1/0;
	}catch(Exception e){
		//新异常实例被捕获
		throw new Exception(e.getMessage());
	}
	return s;
}

如何处理异常
java提供了抛出异常捕获异常的逻辑用于处理异常,当程序抛出异常时,如果不存在捕获异常逻辑,正在执行的方法将在异常处停止执行,并将该异常向外抛出,调用该方法的程序进行相同的处理方式,然后一层一层的向外抛出,直到到达当前程序处时终止线程的执行。

使用场景
java中对异常的处理主要有两种:
一种是使用throws 向上抛出,交给调用者处理,
另一种是使用try-catch进行捕获,自己处理
选择哪种取决于异常应该怎么处理。

使用throws的场景:
	异常必须由容器来处理
		例如:有事物处理的方法中,事务相关的逻辑必须抛出异常,不能捕获,否则会导致事务不回滚。
	本地方法不知道该怎么处理,只有调用方才可能知道如何处理
		例如:一些底层的方法,可能出现多种异常,只要调用方可能根据不同异常做出不同处理,这样只能抛出,而且必须是具体的异常类型,不能是Exception类型。
使用try-catch的场景:
	程序中的语句可能异常不能引起其他逻辑中断;
		例如:缓存逻辑不能引起其他逻辑中断,所以缓存逻辑必须放在try-catch中
	必须对异常进行处理,否则会影响用户体验;
		例如:异常在Controller层,若不处理会报404或500错误页面,有时抛出过多异常会导致程序崩溃,因此,必须使用try-catch处理。

扩展:自定义异常

编写自定义异常,处理输入字符串abc抛出异常,其他不抛出
定义异常MyException,当输入字符串为abc时,抛出异常

public class MyException extends Exception{
	private String errorMsg;
	public MyException(String errorMsg){
		this.errorMsg=errorMsg;
	}
	public String getErrorMsg() {
		return errorMsg;
	}
	public void setErrorMsg(String errorMsg) {
		this.errorMsg = errorMsg;
	}
}

测试类,从控制台输入abc,抛出异常。

public class TestException{
	public static void main(String[] args){
		Scanner scan=new Scanner(System.in);
		String str=scan.nextline();
		if(str.equals("abc")){
			throw new MyException("错了");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值