javaSE-chapter16异常机制

1. java异常机制概述

  1.1 继承体系

    

    Error: 表示错误,一般指JVM相关的不可修复的错误,如:系统崩溃,内存溢出,JVM错误等。由JVM抛出,我们不需要进行处理

    Exception: 表示异常,指程序中出现不正常的情况,该问题可以修复处理。

    RuntimeException: 运行时异常。在编译时期,可以不处理(抛出或捕获处理),编译会通过。但在运行时期可以会产生的异常。常见的如:NullPointerException, ArithmeticException等

    CheckedException: 编译时异常。在编译时期会进行检查,如果没有进行处理(抛出或捕获处理),编译不会通过。常见的如:IOException, SQLException等

public class ExceptionTest {
	
	public void testNullPointerException() {
		throw new NullPointerException();//编译通过
	}
	
	public void testCheckedException() {
		try {
			throw new IOException();//必须进行处理,否则编译不通过
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
}

  1.2 自定义异常

class MyException extends Exception{}
class MyRuntimeException extends RuntimeException{}

public class ExceptionTest {
	
	public void testMyException() {
		try {
			throw new MyException();
		} catch (MyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void testMyRuntimeException() {
		throw new MyRuntimeException();
	}
}

当我们自定义的异常MyException直接继承父类Exception时,也类似于受查异常,必须在编译期进行处理,否则编译不通过。当我们自定义的异常MyRuntimeException直接继承父类RuntimeException时,跟RuntimeException一样,不需要在编译器处理也可以编译通过。


2. 异常处理机制

  2.1 try-catch

    2.1.1 语法结构

        try {

            //可能发生异常的代码(监控区域)

        } catch (ExceptionType1 e1) {

            //当监控区域产生ExceptionType1 类型或其子类的异常时,执行的代码块

        } catch (ExceptionType2 e2) {

            //当监控区域产生ExceptionType2 类型或其子类的异常时,执行的代码块

        } ...

    2.2.2 异常匹配原则

        如果抛出的异常对象属于catch异常的类型或其子类时,则认为生成的异常对象与其异常类型匹配;

        当抛出的异常类型同时与多个catch异常类型匹配时,应该按照代码顺序执行,且一旦被一块catch捕获后,就不能被其他catch捕获了。

public class ExceptionTest {
	public static void main(String[] args) {
		try {
			int a = 1/0;
		} catch (ArithmeticException e) {
			System.out.println("被ArithmeticException捕获...");
		} catch (Exception e) {
			System.out.println("被Exception捕获...");
		}
		System.out.println("end...");
	}
}

结果:

被ArithmeticException捕获...
end...

注意:1.我们一般将子类的Exception放在前面,否则该处代码将永远不会被执行(这种现象叫做异常屏蔽)

          2.一旦try代码块中未抛出异常,或抛出异常后被捕获处理且未再抛出异常,则,try-catch代码块后的代码将会继续执行

  2.2 try-catch-finally

    2.2.1 语法结构

       try {

            //可能发生异常的代码(监控区域)

        } catch (ExceptionType1 e1) {

            //当监控区域产生ExceptionType1 类型或其子类的异常时,执行的代码块

        } catch (ExceptionType2 e2) {

            //当监控区域产生ExceptionType2 类型或其子类的异常时,执行的代码块

         } 

            ......

             finally {

              //最终执行的代码块

          }

    2.2.2 finally代码块:

      2.2.2.1 无论是否捕获处理了异常,finally代码块一般都会执行

      2.2.2.2 如果try或catch代码块中有return语句,则finally代码块会在return语句执行前执行

      2.2.2.3 在几类特殊情况下,finally语句不会被执行:

        在finally语句中发生异常,在语句执行过程中退出了jvm(如:调用System.exit(0)),程序所在的线程死亡等

      2.2.2.4 在方法中如果有返回值和没有返回值,程序调用结果会不同,看下面的实例:

public class MyExceptionTest {
	
	@Test
	public void test() {
		try {
			int a = testThrowOrReturn();
			System.out.println(a);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println(e.getMessage());
		}
	}
	
	private int testThrowOrReturn() throws Exception {
		// TODO Auto-generated method stub
		try {
			System.out.println("try代码块");
			int a = 1/0;
			return a;
		} catch (Exception e) {
			System.out.println("catch代码块");
			throw new Exception("catch中异常");
		} finally {
			System.out.println("finally代码块");
			return -1;
		}
	}	
}

    执行结果:

try代码块
catch代码块
finally代码块
-1

try语句中1/0时抛出异常,被catch语句捕获,打印了catch代码块。之后就执行了finally代码块,返回-1。即catch语句中throw

 new Exception代码并没有执行。如果执行了会被test方法捕获并打印出来。我们从结果看出,并没有打印e.getMessage().

再看下面这个例子:

public class MyExceptionTest {
	
	@Test
	public void test() {
		try {
			testThrow();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println(e.getMessage());
		}
	}
	
	private void testThrow() throws Exception{
		try {
			System.out.println("try代码块");
			int a = 1/0;
		} catch (Exception e) {
			System.out.println("catch代码块");
			throw new Exception("catch中异常");
		} finally {
			System.out.println("finally代码块");
		}
	}
}	

运行结果:

try代码块
catch代码块
finally代码块
catch中异常

catch代码块中的异常有被抛出。在finally代码块执行完成之后(没有返回值),又将atch代码块中的异常抛出。


3. 抛出异常

  3.1 throw

    3.1.1 运用于方法内部,表示抛出一个异常对象,并结束执行当前代码块

  3.2 throws

    3.2.1 运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理该异常(当然方法调用者也可以选择不处理,但必须继续抛出,如果选择抛出,则最终将交给jvm)


4. 最后网上留了一道例题(例题)

package com.tca.thinkInJava.chap12.test;


public class ExceptionDemo {  
    public ExceptionDemo() {  
    }  
   
    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;  
        }  
    }  
   
    public static void main(String[] args) {  
        ExceptionDemo testException = new ExceptionDemo();  
        try {  
            testException.testEx();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

运行结果:

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




猜你喜欢

转载自blog.csdn.net/tca0819/article/details/80471048