Error和Exception

1、finally{}会在catch完成后执行;

2、catch中有return,catch后有finally{}————finally中内容,会在return前执行;

一、简介

Java为我们提供了非常完美的异常处理机制,使得我们可以更加专心的去写程序,有的时候遇到需要添加异常处理块的地方,像eclipse会自动提示你,感觉很幸福!我们看看异常处理的一些类的结构组成:

从根部开始分为两大类:Error和Exception。Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。Exception是程序本身可以处理的异常,这种异常分两大类:非运行时异常(发生在编译阶段,又称checkException)和运行时异常(发生在程序运行过程中,又叫uncheckException)。非运行时异常一般就是指一些没有遵守Java语言规范的代码,容易看的出来,并且容易解决的异常,运行时异常是那些在程序运行过程中产生的异常,具有不确定性,如空指针异常等,造成空指针的原因很多,所以运行时异常具有不确定性,往往难以排查,还有就是程序中存在的逻辑错误,光从一段代码中看不出问题,需要纵观全局才能发现的错误,也会造成运行时异常,这就要求我们在写程序时多多注意,尽量处理去处理异常,当异常发生时,希望程序能朝理想的方面运行!

二、异常的类型

一方面我们可以将异常分为受控异常和不受控异常,其实一般来讲,受控异常就是非运行时异常,不受控异常就是运行时异常和Error。另一方面,我们直接将异常分为非运行时异常和运行时异常。

三、异常处理的过程

使用try/catch/finally语句块安装异常处理程序,每个try块中包含可能出现异常的语句,每个catch块中包含处理异常的程序,


当程序处理不了异常的时候会怎么办?是这样的:当前方法如果声明了相应的异常处理器,如上面的程序如果加了catch(NumberFormatException e),则直接抛出,但是如果没有声明,则会找到它的调用者,如果调用者也没有做相应的处理,则会一直往前找,直到找到main方法,最后抛出异常,所以上面的现象不难解释!此处我们简单总结下异常处理的过程:1、在可能出错的方法加上try/catch块语句,来调用异常处理器。2、当异常发生时,直接跳到相应的异常处理器catch中,如果有则抛出异常,执行该catch块中的语句,如果没有,则找到它的调用者,直到main方法。3、如果有finally块,则执行finally块中的语句。

注意:

1、一个try可对应多个catch。2、有try必须至少有一个catch或者finally(此处经网友actt001指正,多谢!)。3、finally块不是必须的,可有可无。4、一般情况下,当异常发生时,会执行catch块中的语句,特殊情况:当main方法中抛出异常时,如果程序声明了该异常处理器,则执行相应的catch块中的语句,如果程序没有声明相应的异常处理器,则不执行catch块中的语句,直接抛出异常!那么,这个异常来源于哪儿?既然main中有try/catch语句(虽然不是对应的异常处理器),为什么没有抛出,说明main方法中的try/catch块根本就没有捕捉到异常,那么系统怎么处理?其实是这样的,这种情况下,异常被直接丢给JVM,而JVM的处理方式就是:直接中断你的程序!就是这么简单。

四、常见异常

NullPointerException 空指针

空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等

ClassNotFoundException  找不到类

找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。

ClassCastException   类型转换

ArithmeticException   算数条件

算术条件异常。譬如:整数除零等。

ArrayIndexOutOfBoundsException  数组越界

数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。


五、异常和错误

异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是JVM(Java虚拟机)通知你的一种方式,通过这种方式,JVM让你知道,你已经犯了个错误,现在有一个机会来修改它。Java中使用异常类来表示异常,不同的异常类代表了不同的异常。但是在Java中所有的异常都有一个基类,叫做Exception。

错误:它指的是一个合理的应用程序不能截获的严重的问题,大多数都是反常的情况,错误是JVM的一个故障(虽然它可以是任何系统级的服务)。所以,错误是很难处理的,一般的开发人员是无法处理这些错误的,比如内存溢出。

1、finally和return问题

我们平时说:finally中的内容不论程序有无异常,都会被执行,那么如果我们的程序在try和catch块中return了,finally中的还会执行吗?读者可以先猜猜看,分析一下,接下来我们做实验:

[java]  view plain copy
  1. public class FinallyTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         boolean file = open();  
  5.         System.out.println("this is main return value:" + file);  
  6.     }  
  7.   
  8.     public static boolean open() {  
  9.         String filename = "d:\\test.txtp";  
  10.         try {  
  11.             FileReader reader = new FileReader(filename);  
  12.             Scanner in = new Scanner(reader);  
  13.             String input = in.next();  
  14.             int value = Integer.parseInt(input);  
  15.             System.out.println(value);  
  16.             return true;  
  17.   
  18.         } catch (FileNotFoundException e) {  
  19.             System.out.println("this is catch_for_filenot... block!");  
  20.             return false;  
  21.         } finally {  
  22.             System.out.println("this is finally block!");  
  23.         }  
  24.     }  
  25. }  

故意把filename写错,造出异常,输出为下:

this is catch_for_filenot... block!
this is finally block!
this is main return value:false

从这儿看出来,程序先输出catch块中的,后又去执行finally块中的,虽然在catch中已经返回了,最后执行mian方法中的,而且输出false,说明catch块中的也成功返回了。所以,面对疑问,我们可以很肯定的回答,即使有return语句,finally块也一定会被执行!

2、尽量不要将catch和finally一起使用。

像我上面演示程序那样,try/catch/finally一起使用,在《Big Java》一书中提到,不建议这样做,因为会影响程序的可读性,最好的做法是:用try/catch嵌套,catch用来捕获异常,finally用来关闭资源,修改如下:

[java]  view plain copy
  1. public class FinallyTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.           
  5.         boolean file = open();  
  6.         System.out.println("this is main return value:" + file);  
  7.     }  
  8.   
  9.     public static boolean open() {  
  10.           
  11.         String filename = "d:\\test.txtp";  
  12.         try {  
  13.             try {  
  14.                 FileReader reader = new FileReader(filename);  
  15.                 Scanner in = new Scanner(reader);  
  16.                 String input = in.next();  
  17.                 int value = Integer.parseInt(input);  
  18.                 System.out.println(value);  
  19.                 return true;  
  20.   
  21.             } finally {  
  22.                 // 一些关闭资源的操作  
  23.                 System.out.println("this is finally block!");  
  24.             }  
  25.   
  26.         } catch (FileNotFoundException e) {  
  27.             System.out.println("this is catch_for_filenot... block!");  
  28.             return false;  
  29.         }  
  30.     }  
  31. }  



产生虚拟机栈或本地方法栈StackOverFlow当请求的栈深度超过JVM允许最大深度

/*
 *VM args: -Xss128K
 */
public class JavaVMStackSOF {
<span style="white-space:pre">	</span>private int stackLength = 1;
<span style="white-space:pre">	</span>public void stackLeak() {
<span style="white-space:pre">		</span>stackLength++;
<span style="white-space:pre">		</span>stackLeak();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>public static void main(String[] args) throws Throwable {
<span style="white-space:pre">		</span>JavaVMStackSOF oom = new JavaVMStackSOF();
<span style="white-space:pre">		</span>try {
<span style="white-space:pre">			</span>oom.stackLeak();
<span style="white-space:pre">		</span>} catch(Throwable e) {
<span style="white-space:pre">			</span>System.out.println("stack length:" + oom.stackLength);
<span style="white-space:pre">			</span>throw e;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}

产生虚拟机栈或方法栈OutOfMemory不断创建线程

/*
 * VM args: -Xss2M
 */
public class JavaVMStackOOM {
	private void dontStop() {
		while (true) {
			
		}
	}
	
	public void stackLeakByThread() {
		while (true) {
			Thread thread = new Thread(new Runnable() {
				@Override
				public void run() {
					dontStop();
				}
			});
			thread.start();
		}
	}
	
	public static void main(String[] args) {
		JavaVMStackOOM oom = new JavaVMStackOOM();
		oom.stackLeakByThread();
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值