浅谈异常处理机制

try - catch - finally - throw - throws 的使用场景

浅谈异常处理机制


​ 首先需要知道的是Java中的异常机制(throw able) 其中可大分为两种

一、错误(Error)

错误一般是程序逻辑上是没有问题,通常是虚拟机异常所导致的。

​ 如:

public class ErrorTest{
    public static void main(String[] args)
    {
        test();
    }
    private static void test(){
        System.out.println("这是test方法");
        test();
    }
}

这段代码在逻辑上是没有问题的,理论上也是不会存在错误的,但是我们跑起来后,就会发现控制台上给我们提示了错误

com.zhjaid.Course.dy1103.CustomException
这是test方法
这是test方法
这是test方法
...
这是test方法
这是test方法
这是test方法Exception in thread "main" java.lang.StackOverflowError
	at sun.nio.cs.ext.DoubleByte$Encoder.encodeLoop(Unknown Source)
	at java.nio.charset.CharsetEncoder.encode(Unknown Source)
	at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)

这就能看到了,系统提示了一个 java.lang.StackOverflowError ,看到了名字估计就能明白了,这是栈内存溢出的异常。也就是说栈当中的栈帧已经存满了,不能再继续放下新的栈帧了,所以就报出了这个错误。

二、异常(Exception)

异常就是平时我们接触的相对比较多的了,然而异常又可细分为两种。检测时异常、运行时异常。

1、检测时异常 (Cheek Exception)
1)什么是检测时异常呢?

​ 检测异常就是在我们编写代码的时候编辑器所能检测出来并提示我们try-catch的代码块。常见的文件输入输出流。FileInputStream 构造这个类的时候,编辑器会强制让我们处理一个FileNotFoundException异常。如果检测异常不处理的话编译是不会通过的,就更别谈运行了。

如:

try {
		FileInputStream inputStream=new FileInputStream(new File("C:filePath"));
	} catch (FileNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
2)常见的检测时异常
异常名字释义
FileNotFoundException找不到文件异常
SQLException操作数据库异常
IOException输入输出流异常
ClassNotFoundException类未找到异常
2、运行时异常(Runtime Exception)
1) 什么是运行时异常?

运行时异常就与检测异常不一样了,上面说到了检测异常是已知的必须处理的。而运行时异常是运行中程序不可预见的。也就是语法逻辑上没有错误,编辑器也不会提示你有异常,需要等到运行时某个参数传到了某个方法块里面处理逻辑的时候,才发现这个参数不满足代码处理的需求,从而导致系统抛出Runtime Exception。

如:

String str=null;
boolean s=str.equals("str");

​ 这里假设一个场景:一个字符串声明或者从其他方法返回为空时,这个时候,这个str仅仅是在栈中有引用,但是在堆中是没有具体的引用对象的,这时候调用 str.qeuals(); 的时候,就会得到以下的结果。

Exception in thread "main" java.lang.NullPointerException
	at com.pager.test.s.sad.main(StringTest.java:12)
2)如何避免运行时异常?

那么,我们怎么避免这个问题呢?加上try代码块就行了。

try {
    	String str=null;
    	boolean s=str.equals("str");
	} catch (Exception e) {
		e.printStackTrace();
    	System.out.println("出现了异常");
	}

​ 运行结果如下:

java.lang.NullPointerException
出现了异常
	at com.pager.test.s.sad.main(StringTest.java:13)
3)常见的运行时异常
异常名释义
NullPointerException空指针异常,当被调用对象为空时会出现
IndexOutOfBoundsException数组下标越界异常,访问的数组索引大于当前数组的长度
ClassCastException类型转换异常
NumberFormatException数字格式化异常
ArithmeticException算数异常
三、Finally 结束语句
1、什么是Finally?

Finally 翻译过来就是最后,最终的意思。try-catch-finally是一套完整的异常处理流程。finally 是位于整个异常处理语句的最后,当try和catch的逻辑都执行完成后就会执行finally里的逻辑。且如果写了finally语句块的话,无论try和catch执行结果怎样,返回参数怎样,都会执行finally。

2、Finally 示例
1)方法定义

​ 这里定义一个 test() 方法并写好整个异常处理逻辑

	public static int test(){
		int num=0;
		try {
			  System.out.println(2/0);
			  return num++; 
		}catch(ArithmeticException e) {
			return -1;
		}finally {
			return num;
		}
    }

​ 打印出2除0的结果。我们从小学就学了,0是不能被作为除数。按照正常的逻辑,如果这里用2除0的话,就会抛出一个 ArithmeticException 算数异常,从而进入catch语句,返回 -1 然后程序结束,是这样吗?

2)运行结果

​ 运行结果如下:

System.out.println(test());

===>>> 0

返回的是0,这不符合逻辑啊,是不是catch异常里出了问题?下面我把代码改正确,然后再看看返回值。

3)修改代码

​ 这里把 2/0 改成了10/2

	public static void main(String[] args) {
		System.out.println(test());
	}

	public static int test(){
		int num=0;
		try {
			  System.out.println(10/2);
			  return num++; 
		}catch(ArithmeticException e) {
			return -1;
		} finally {
			return num;
		}
    }

===>>>
5
1

改成 10/2 后看到了打印出了 5 和 1 。5还能理解, 10/2 的结果就是 5 嘛。但是 1 是哪里来的呢?

4)分析结果

​ 其实通过 num 变量的值就能看出来,num 是已经执行了try 里面的return num++ 的返回操作。

​ 前面已经说过了,不管 try 和 catch 的 return 结果如何,都会再执行 finally 里的 return 数据。

5)结论

1、不管有没有出现异常,finally块中代码都会执行;

2、当try和catch中有return时,finally仍然会执行,且 return 值以 finally为准;

3、finally是在return后面的表达式运算后执行的,此时并没有返回运算后的值,而是先把要返回的值保存到了栈帧中的返回地址

四、try - catch -finally 处理语句的总结

1、catch 语句块异常类必须是从上往下为子类到父类的顺序。因为父类的能捕获的范围更大。

2、try 为异常处理块里的必要关键字。catch 和 finally 不是必须存在的,但是 catch 和 finally 二者必须存在至少一个。

3、如果写上了finally 语句块,则无论是否发生异常,finally 里的逻辑必定会被执行。

4、当try和catch中有return时,finally仍然会执行。try和catch中的return会先执行,且 return 值以 finally为准;

五、throw、throws(抛出异常)
1、throw 抛出异常

​ throw 是语句抛出一个异常,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常。

​ 如:

public static void main(String[] args) { 
    String s = "abc"; 
    if(s.equals("abc")) { 
      throw new NumberFormatException(); 
    } else { 
      System.out.println(s); 
    } 
}

​ 结果:

Exception in thread "main" java.lang.NumberFormatException at......
2、throws 抛出异常声明

​ throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)

public void function() throws Exception{
	//...
}

​ 调用:

try { 
	function(); 
} catch (Exception e) { 
	System.err.println("出现了异常"); 
    //e.printStackTrace(); 
} 

​ 这里就可以发现,使用了 throws 的方法在我们调用的时候会产生一个检查时异常 需要我们手动捕获和处理。

3、throw 、throws 二者区别

​ 1)throws出现在方法头;而throw出现在体内。

​ 2)throws表示出现异常的一种可能性,并不一定会发生这些异常;

​ throw则是生产并且抛出了异常,执行throw则一定抛出了某种异常对象。

六、完结

学无止境、特作此记录。

现了异常");
//e.printStackTrace();
}


​	这里就可以发现,使用了 throws 的方法在我们调用的时候会产生一个[检查时异常]() 需要我们手动捕获和处理。

##### 3、throw 、throws 二者区别

​	1)throws出现在方法头;而throw出现在体内。

​	2)throws表示出现异常的一种可能性,并不一定会发生这些异常;

​		throw则是生产并且抛出了异常,执行throw则一定抛出了某种异常对象。



#### 六、完结

学无止境、特作此记录。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值