java异常处理Exception

       我看别人的面经中有一道题目就问到了Exception,即java的异常处理的,我以前也学了java的异常处理,但是我查了下,看了别人的博客关于写的exception异常处理,我发现,自己学的不牢固,只学到了一点皮毛而已,在看了那么多博客和资料后,我做下总结吧,不然我大脑都混乱了。

      java的中异常祖先是Throwable,Throwable的直接子类是Exception和Error。

      Error通过单词我们就知道,是错误的意思,这种错误一般是jvm运行产生的错误,出现这种错误,我们的程序不能解决,比如内存溢出oom,堆溢出等。这种错误,我们不必处理,直接让jvm抛出报错,我们没办法解决就不管了。

     Exception中文意思是异常,那么Exception又分为检查性异常和非检查性异常。比如RuntimeException类及子类就是非检查性异处,表示运行时出现的异常,有数组越界,空指针异常,我们也可以不进行处理,让jvm自己抛出异常,当然如果我们可以预见这种异常的话,最好在程序中进行判断检查,程序写健壮些,有的这种异常就可以避免了。effect java有这种处理的推荐,具体的可以看看这本书。

    Exception还有一类是检查性异常,这是除RuntimeException类及子类外的Exception类和Exception类的其他子类。检查性异常,必须要进行异常处理的或者抛出,否则编译器会报错。

      

   异常处理一般用到以下几个关键字try,catch,finally,throws,throw,下面我逐个做一个说明。

    try:

    对于可能会抛出异常的代码一般放在try{}代码块中,比如:

 

try {
  int   i=2/0;
			t.test1();
			//System.out.println("kkk"+st);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("i will catch you....");
			e.printStackTrace();
		}


上面的代码2/0,肯定会抛出异常的,所以需要放在try{}块中,在try块中,如果哪一行抛出了异常,那么try块后面的代码将不再执行,将直接进入异常处理代码块。


  catch:

    catch(Excetion e){}这种结构是用来处理,try代码块中抛出的异常的,可以有很多的catch代码块,不过要注意的是,当有很多catch代码块,并且catch里面的参数有父子关系的时候,catch里面的参数一定要是子类在前面,父类在后面,因为按catch代码块出现的先后顺序匹配抛出的异常,一旦抛出的异常是哪个catch里面参数的子类或同类,那么就可以被这个catch代码块进行处理,那么其他的catch代码块就算也符合这种条件也不在进行处理了,如果有finally代码块的话就直接进入finally代码块中,没得则直接运行catch代码块后面的代码了。


    finally:

    finally代码块是异常处理中一定会执行的代码块,就算没得异常也会执行,有异常则进入catch代码块中处理后,在进入finally中处理。

    在这里要注意一点,假如在try代码块中有return 语句,那么也是先执行finally里面的代码块后在执行return语句的。

 还需注意一点的是,函数的返回值,是最后活动栈的栈顶的值。如果try进行return了,那么在finally中我也进行return,那么finally代码块里面的return的值在栈顶,所以会返回finally中return的值。有如下测试代码。

package com.wj.exception;

public class TestException3 {

	
	public String testException(){
		try{
			return "I am in try";
		}finally{
			return "I am in finally";
		}
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		System.out.println(te.testException());
	}

}


运行结果是:

   I am in finally


注意我这里是测试所以在finally中进行return了,一般不推荐在finally中进行return。



    throws:

    throws的用法是在      函数名(参数1,参数2.....)throws 异常类1,异常类2,异常类3.....{}

   throws是表明这个函数可能会有异常产生,但是函数不进行异常处理,函数将向上抛异常,把异常处理交给函数的调用处进行处理,如果调用处,不进行处理则可以在进行向上抛。。。直到有地方进行try{}catch(){}异常处理,或者最后抛给jvm(不建议这么使用)。

package com.wj.exception;

public class TestException3 {

	
	public String testException() throws Exception{
		/*try{
			return "I am in try";
		}finally{
			return "I am in finally";
		}*/
		System.out.println("我不进行异常处理,我将异常向上抛,throws");
		int i=2/0;
		System.out.println("有异常我将得不到执行。。。。");
		return "我是使用throws抛的异常";
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		try {
			System.out.println(te.testException());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


输出结果:

<span style="font-size:18px;">我不进行异常处理,我将异常向上抛,throws
java.lang.ArithmeticException: / by zero
	at com.wj.exception.TestException3.testException(TestException3.java:13)
	at com.wj.exception.TestException3.main(TestException3.java:24)
</span>



       throw:

     throw的作用是具体的抛出一个异常类对象,一般在方法里面使用。当在try代码块中使用的时候,直接进入catch代码块中进行处理。比如:

package com.wj.exception;

public class TestException3 {

	
	public String testException(){
		try{
			throw new Exception("i is throw exception");
		}catch(Exception e){
			System.out.println("我处理throw抛出的异常");
		}finally{
			System.out.println("我执行finally代码块\n");
			
		}
		System.out.println("异常处理结束!!!");
		return "I am in finally";
		
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		
	    System.out.println(te.testException());
		
	}

}


允许结果:

我处理throw抛出的异常
我执行finally代码块


异常处理结束!!!
I am in finally



        throw手动抛出的异常需要从里到到外查找处理的try代码块,没有处理话,就需要把方法后面加throws,把异常向上抛。看如下代码:


    1

package com.wj.exception;

public class TestException3 {

	
	public String testException(){
		try{
			int i=3/0;
		}catch(Exception e){
			throw new Exception();
		}finally{
			System.out.println("我执行finally代码块\n");
			
		}
		//System.out.println("异常处理结束!!!");
		return "I am in finally";
		
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		
	    System.out.println(te.testException());
		
	}

}





2

上面的代码在编译器里面会出现错误,提示我们使用throws抛出异常,或者把throw new Exception()进行因此处理,改成这样的

<pre name="code" class="java">package com.wj.exception;

public class TestException3 {

	
	public String testException() {
		try{
			int i=3/0;
		}catch(Exception e){
			try {
				throw new Exception();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}finally{
			System.out.println("我执行finally代码块\n");
			
		}
		//System.out.println("异常处理结束!!!");
		return "I am in finally";
		
	}
	
	
	public static void main(String[] args)  {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		
	    
			System.out.println(te.testException());
		
		
	}

}

 


输出结果:

java.lang.Exception
	at com.wj.exception.TestException3.testException(TestException3.java:11)
	at com.wj.exception.TestException3.main(TestException3.java:32)
我执行finally代码块

I am in finally









3

或者说是这样的:

<pre name="code" class="java">package com.wj.exception;

public class TestException3 {

	
	public String testException()  throws Exception{
		try{
			int i=3/0;
		}catch(Exception e){
			
				throw new Exception();
			
		}finally{
			System.out.println("我执行finally代码块\n");
		}
		//System.out.println("异常处理结束!!!");
	return "I am in finally";
		
	}
	
	
	public static void main(String[] args)  {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		
	    try {
			System.out.println(te.testException());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

输出结果:

 
我执行finally代码块


java.lang.Exception
<span style="white-space:pre">	</span>at com.wj.exception.TestException3.testException(TestException3.java:11)
<span style="white-space:pre">	</span>at com.wj.exception.TestException3.main(TestException3.java:28)







4

这样改,很简单,但是还有一种更加奇葩的改法,可以使编译器不出错,如下:

package com.wj.exception;

public class TestException3 {

	
	public String testException()  {
		try{
			int i=3/0;
		}catch(Exception e){
			
				throw new Exception();
			
		}finally{
			System.out.println("我执行finally代码块\n");
			return "I am in finally";
		}
		//System.out.println("异常处理结束!!!");
		//return "I am in finally";
		
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException3 te=new TestException3();
		
	    System.out.println(te.testException());
		
	}

}

输出:

我执行finally代码块
I am in finally




     发现没有第四个代码,本来是跑出了一个异常的,但是没有输出任何的异常信息。而且把函数返回值改为void,在finally里面不使用return,则又会报错,这一点我不是很明白了,难道在catch里面使用throw抛出的异常,在finally代码块里面使用return语句后,就被处理了嘛?要是被处理了怎么没得异常输出,还是输出的异常信息在栈里面被覆盖了?知道怎么回事的朋友,可以交流下。


看了上面那么多,你是否对java中的异常有一定理解了?

我在博客http://blog.csdn.net/hguisu/article/details/6155636里面看到一个例子,貌似比较经典,就借用下了,代码如下了:

package com.wj.exception;

public class TestException1 {

	boolean testEx() throws Exception {  
	boolean ret = true;  
	try {  
	ret = testEx1();  
	} catch (Exception e) {  
	System.out.println("testEx, catch exception");  
	ret = false;  
	throw e;  
	} finally {  
	System.out.println("testEx, finally; return value=" + ret);  
	return ret;  
	}  
	}  

	
	boolean testEx1() throws Exception {  
	boolean ret = true;  
	try {  
	ret = testEx2();  
	if (!ret) {  
	return false;  
	}  
	System.out.println("testEx1, at the end of try");  
	return ret;  
	} catch (Exception e) {  
	System.out.println("testEx1, catch exception");  
	ret = false;  
	throw e;  
	} finally {  
	System.out.println("testEx1, finally; return value=" + ret);  
	return ret;  
	}  
	}  

	boolean testEx2() throws Exception {  
	boolean ret = true;  
		try {  
		int b = 12;  
		int c;  
		for (int i = 2; i >= -2; i--) {  
		c = b / i;  
		System.out.println("i=" + i);  
		}  
		return true;  
		} catch (Exception e) {  
		System.out.println("testEx2, catch exception");  
		ret = false;  
		throw e;
		} finally {  
		System.out.println("testEx2, finally; return value=" + ret);  
		return ret;  
		}  
		}  

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		TestException1 testException1 = new TestException1();  
		try {  
		testException1.testEx();  
		} catch (Exception e) {  
			System.out.println("结束\n");
		e.printStackTrace();  
		}  

	}

}

如果不看答案,你能说出运行结果嘛?你可以到自己的编译器中运行下看下结果,在进行debug下,看看是否和你想的一样了。







      上面运行的结果如下:

i=2
i=1
testEx2, catch exception
testEx2, finally; return value=false
testEx1, finally; return value=false
testEx, finally; return value=false


   我进行过debug,所以我清楚运行的流程,但是对于内部的机制,还有点疑点,就像我在4所说的,finally中的return 会覆盖throw抛出的异常一样,真的是这样的嘛,如果是这样的话,上面的代码就能分析出和运行一样的输出结果了,可以试试,一起交流下。



本文原创,转载请著明:http://blog.csdn.net/j903829182/article/details/39808307






















































































































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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值