“Java异常Exception”总结

1. 异常(Exception)。 
2. Java中的异常分为两大类: 
a) Checked exception  (非  Runtime Exception) 非运行时异常 
b) Unchecked exception(Runtime Exception) 运行时异常 
3. Java中所有的异常类都会直接或间接地继承自Exception。 
4. RuntimeException类也是直接继承自Exception类,它叫做运行时异常,Java中所有 
的运行时异常都会直接或间接地继承自RuntimeException。 
5. Java 中凡是继承自Exception而不是继承自RuntimeException的类都是非运行时异 
常。 如附件图:运行—非运行异常区分.jpg 

6.异常处理的一般结构是: 
try 


catch(Exception e) 


finally 


无论程序是否出现异常,finally 块中的代码都是会被执行的。 
7. 对于非运行时异常(checked  exception),必须要对其进行处理,处理方式有两种: 
第一种是使用try.. catch…finally 进行捕获;第二种是在调用该会产生异常的方法所在 
的方法声明throws Exception 继续往外抛。 
8. 对于运行时异常(runtime  exception),我们可以不对其进行处理,也可以对其进行处理。推荐不对其进行处理。 
9. NullPointerException是空指针异常,出现该异常的原因在于某个引用为null,但你却调用了它的某个方法。这时就会出现该异常。 

10.Error和Exception之间关系:程序可能会发生错误Error,可能会出现异常Exception。异常是我们可以处理的情况,但是如果程序发生了错误,我们就不能处理了。错误的危险级别比异常更高。一般情况下如果我们在代码上不做任何处理的话,程序发生了异常,那么异常代码后面的代码就不会再去执行了,但是如果我们对异常代码提前做了相应的处理(比如抛出或捕获),那么当异常发生的时候,代码还是能够继续往下执行的;而对于错误Error,我们无能为力,没有办法做任何处理,也没有任何办法让错误代码下面的代码继续执行。 

系统对于运行时异常和非运行时异常的处理方式是完全不一样的。 


Java里面每一个异常都是一个类,当程序执行到某一行如果出现异常的话,它会在可能产生异常的这一行代码的位置处产生一个针对于这个异常的一个异常对象(至于是哪个异常类型的对象,它会根据实际的异常情况自己去选择),这个对象是由它运行的时候来去动态的去生成的。如下代码: 
Int c = 0; 
Try { 
Int a = 3; 
Int b = 0; 
C = a / b; 
} catch (ArithmeticException e) { 
e.printStrackTrace(); 

如果出现异常,会生成一个异常类对象,这个对象直接赋给引用变量e。 


注意:在try块里面,如果某行代码出现异常了,那么流程会直接从这行代码转到catch块里面,try块里面此行代码后面的代码不会再去执行了。Catch块完了之后再往后正常去执行catch块后面的代码。 


可能发生异常的代码放到try里面。一定要执行的代码放到finally里面。 

程序光有try和finally,没有catch也是可以的。也是可以正常编译通过的。这样就相当于没有对异常进行处理,和不加try、catch是一个效果,后面的代码不会再去执行。 
一个try后面不论跟着多少个catch,最多只会有一个catch被执行。 


在一个方法里面我们可以自己手工的去抛出异常,用关键字throw,抛出的是异常对象(异常出现的时候产生的也是异常对象)。如下代码作解释: 




所有的异常实际上都是对象。 


异常的第一种方式是try  catch捕获,第二种方式是抛出异常,抛出异常是由调用这个方法的那个方法对这个异常进行处理,它的处理方式也是有两种,要么捕获,要么继续抛出,继续抛给调用它的方法,就这样一层一层的网上抛。最后,main方法是我们的最后一个方法,如果main方法我们也声明为抛出的方式,那么最后异常就会抛给Java虚拟机了,由虚拟机自己去处理。 

真正抛出异常对象的地方都是在程序代码里面,比如某行代码出异常了,程序会自动的生成一个相应的异常对象然后抛出,也可能是我们在代码里面某些地方自己手动的抛出异常对象,这个也是先new出来一个相应的异常对象,然后抛出(throw);而在方法声明的时候写的比如throws Exception,它不是真正的抛出异常对象,而只是做出一个声明,声明我的这个方法有可能会抛出异常,同样的也告诉调用这个方法的调用端我的这个方法有可能会抛出异常,调用端你也同样的需要做好抛出异常的准备(调用端方法声明中声明throws Exception)。就这样你调用我,他调用你,你把我这里抛出的异常继续往上抛,他把你这里出来的异常也继续往上抛,就这样一层层的,一直往上抛,最后把异常抛给了Throwable,由它来处理。 


下面讲解自定义异常: 

所谓自定义异常,通常就是定义了一个继承自Exception类的子类,那么这个类就是一个自定义异常类。通常情况下,我们都会直接继承自Exception类,一般不会继承某个运行时的异常类。 

自定义异常本身非常简单,不难,但是在实际开发里面几乎每个项目或多或少都会用到自定义异常,比如说你做了一件事情,比如用户在登录或是什么时候,用户名或密码错了之类的,遇到这些情况一方面是可以通过判断(if...else…),另外一方面也可以通过抛异常的方式处理。 

自定义异常类都需要继承Exception类。 

异常2中处理方式的比较:采用抛出的方式,程序一旦出现异常就一定不会再往下继续执行了;而采用try…catch…方式,程序一旦出现异常还是可以继续往下执行。 

下面是一个自定义异常的实例(重点掌握): 

package com.shengsiyuan.exception;

/**
 * 自定义异常
 * 自定义异常类都需要继承Exception类。
 * 自定义异常一般都有两个构造方法,一个不带参数的空的构造方法,一个接收一个字符串参数的构造方法。
 * 类: MyException 
* 描述: TODO
* 作者: * 时间: Oct 30, 2013 11:02:15 AM */ public class MyException extends Exception { public MyException() { super(); } // 这个方法接收的参数message一般为异常发生时的提示信息。 public MyException(String message) { // 调用父类Throwable里面接收一个字符串参数的构造方法,它会把这个message的值赋给Throwable里面的detailMessage变量,detailMessage这个变量一般就是Throwable类在处理异常时(因为大多数异常最后都是抛给了它,由它来统一处理,当然,利用try...catch...捕获除外。要么最后抛出到Throwable处理,要么捕获处理)给出的提示信息。 super(message); } }

package com.shengsiyuan.exception;

/**
 * 自定义异常使用示例
 * 类: ExceptionTest4 
* 描述: TODO
* 作者: * 时间: Oct 30, 2013 11:52:47 AM */ public class ExceptionTest4 { public void method(String str) throws MyException { if (null == str) { // 抛出异常对象,一层层随着方法之间的调用往上抛,一直到最后抛给Throwable来处理该异常 throw new MyException("传入的字符串参数不能为null"); } else { System.out.println(str); } } /** * 演示异常的两种处理方式 * 方法: main
* 描述: TODO
* 作者: * 时间: Oct 30, 2013 11:58:22 AM * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // 异常的第一种处理方式(抛出) ExceptionTest4 test4 = new ExceptionTest4(); test4.method("hello"); // 代码执行到这行就会产生异常并抛出,后面的代码就不会再去执行了。 test4.method(null); System.out.println("test"); // // 异常的第二种处理方式 // try { // ExceptionTest4 test = new ExceptionTest4(); // test.method(null); // } catch (MyException e) { // e.printStackTrace(); // } finally { // System.out.println("异常处理完毕"); // } // System.out.println("程序执行完毕"); } }


Try…catch…finally结构里面的catch块可以有多个。每一个catch块捕获着一种特定类型的异常。总之凡是被调用方法有可能抛出的所有异常类型(一个方法是可以抛出多个异常类型,也可以抛出多个异常之间共有的父类,比如Exception来代替多个异常类型来抛出),你这里在catch块里面全都要捕获到,定义一个catch块不行就定义两个,定义两个不行就定义三个(也可以定义一个多个异常之间共有的父类来代替多个异常也可以,比如Exception),一直到都能捕获到为止。相应的异常出现的时候就进入到相应类型的catch块里面,但顶多只能有一个catch块被执行。 


对于异常捕获来说,可以通过多个catch来去捕获我们的这个异常,但是一定要注意,他们的这种顺序关系是按照子类跟父类这种关系来排列的。顺序是按照子类在前父类在后的顺序来的,子类在前,父类在后,表示范围小的在前面(是针对多个catch块之间的异常类存在继承关系来说的),如果父类型的放在前面那么后面的子类型就没法去执行了就没有意义了。如果catch块和catch块之间的异常类型没有关系不存在继承关系,那么谁在前谁在后都可以。总结如下: 
我们可以使用多个catch块来捕获异常,这时需要将父类型的catch块放到子类型的catch块后面,这样才能保证后续的catch可能被执行,否则子类型的catch将永远无法到达,Java 编译器会报编译错误;如果多个catch 块的异常类型是独立的(MyException, MyException2),  那么谁前谁后都是可以的。 

如果try 块中存在return 语句,那么首先也需要将finally 块中的代码执行完毕,然后方法再返回(当然finally块后面的代码不会执行了。这种问题很无聊,根本没有什么实际用处,面试的时候会遇到,记住就行。)。 

如果try 块中存在System.exit(0)语句,那么就不会执行finally 块中的代码,因为 
System.exit(0)会终止当前运行的Java虚拟机,程序会在虚拟机终止前结束执行(这种问题也很无聊,没用。记住就行。)。 


下面示例是一个实际开发中经常用到的一种使用异常的情况(相当于先把当前的异常捕获了,然后转换成自定义的异常抛出,给出用户自定义的提示处理异常): 
package com.shengsiyuan.exception;

public class ExceptionTest5 {
	public void method() throws MyException {
		try {
			System.out.println("进入到try块");
			int a = 1;
			int b = 0;
			int c = a / b;
		} catch (Exception e) {
			System.out.println("异常发生了");
			// 相当于把当前可能出现的异常类型转化了,转化成自己自定义的异常类型,然后给用户相应的自定义信息并处理该异常。
			throw new MyException("转到自定义异常给用户提示!");
		} finally {
			System.out.println("进入到finally块");
		}
	}

	public static void main(String[] args) {
		ExceptionTest5 test = new ExceptionTest5();
		try {
			test.method();
		} catch (MyException e) {
			e.printStackTrace();
		}
	}
}

你可能感兴趣的:(Web框架)