异常

一、异常的概念

        异常的概念:在java程序运行过程中,出现的不正常的情况,出现的错误,称为异常。

        异常就是一个对象,描述了那些不符合正常运行的情况,包含了这些情况的原因、类型、描述以及位置,这些内容都封装到异常对象中。

        Java程序运行过程中所发生的异常事件可分为两类:

        Error:JAM系统内部错误、资源耗尽等严重情况

        Exception:其它因编程错误或偶然的外在因素导致的一般性问题。比如:空指针访问、试图读取不存在的文件等

二、异常的处理机制

         在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。

        抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。        

         捕捉异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。 

         在jvm中默认处理异常的机制

         1.在代码的某个位置,出现和正常情况不同的情况,就将异常封装到一个异常对象。

         2.将异常对象抛给调用该方法的方法。

         3.某个方法接收到抛过来的异常,也没有办法自己处理,继续向上抛出,最终抛给主方法,主方法也没有办法处理,抛给调用自己的jvm虚拟机。

         4.JVM只能将错误信息通过错误流打印出来。

         手动处理异常的方式(两种方式)

         异常的声明:某个方法有编译时异常,编译就会无法通过,需要在异常所在的方法声明上,声明该方法可能出现的编译异常。

         异常的处理:出现异常之后,可以通过某些格式来捕获和处理异常,可以定义自己处理异常的逻辑。

         捕获处理异常的格式:

           try...catch

           try...catch...finally

           try...finally

            (1)异常捕获处理的第一种格式(方式一)

            格式

            try{

                     可能发生异常的代码

           }catch(){

                    这种异常出现之后的处理方式

           }

           运行机制

           1.运行try语句中的代码,检测。

           2.如果没有发生异常,那么不再运行catch块中的内容。

           3.如果发生了catch块中声明的异常,那就会捕获到这个异常,并且进行处理,后面的程序可以继续执行。

           4.如果发生catch中没有声明的异常,那么就无法捕获异常,该异常的处理机制就是jvm的默认处理机制。

          代码示例

public class Test {

	public static void main(String[] args) {
		test01();		//长点心吧,不要再瞎搞的
	}					

	private static void test01() {
		test02();		
	}

	private static void test02() {
		try {
			//int i = 1/0;	
			int[] arr = new int[5];
			arr[6] = 7;
		}catch(ArrayIndexOutOfBoundsException e) {
			//处理异常的代码
			//System.out.println("除零异常发生,请重新运行程序");
			System.out.println("长点心吧,不要再瞎搞的");
		}
		
	}

}

            (2)异常捕获处理的第一种格式(方式二)

            格式

             try{

             }catch(异常类型1 异常对象){

             }catch(异常类型2 异常对象){

             }

             在jdk1.7之后可使用此方式

             catch(异常类型1 | 异常类型2 异常对象名){

             异常类型1 | 异常类型2的共同处理方式

            }

             catch(Exception e)模块一般都写在catch块的最下面。

            代码示例

public class Test {

	public static void main(String[] args) {
		try {
			//int i = 1/0;出现算术异常了...
			//int[] arr = new int[5];
			//arr[7] = 10;出现算术异常了...
			Object obj = null;
			Class clazz = obj.getClass();//出现空指针异常了...
		}catch(ArithmeticException | ArrayIndexOutOfBoundsException e) {
			System.out.println("出现算术异常了...");			
		}catch(NullPointerException e) {
			System.out.println("出现空指针异常了...");
		}catch(Exception e) {
			
			
		}
	}
}

            (3)异常捕获的第二种格式

            格式

             try{

                         可能发生异常的代码

            }catch(Exception e){

                         当前异常的处理方式

            }finally{

                         一定要执行的代码

            }

            代码示例

public class Test {

	public static void main(String[] args) {
		try {			
			//int i = 1 / 1;  finally中一定会执行的语句

			/*int[] arr = new int[5];
			arr[7] = 10;*/   //出现异常了...
							 //finally中一定会执行的语句

		} catch (Exception e) {
			System.out.println("出现异常了...");
		}finally {
			//一定会执行的代码块  释放资源
			System.out.println("finally中一定会执行的语句");						
		}
	}
}

            (4)异常处理的第三种格式

            格式

             try{

                          可能发生异常的代码;

            }finally{

                        一定会执行的代码

            }

            作用:如果有两句代码,都需要执行,不希望第一句代码执行成功与否影响第二句的执行,那么就把这两句代码分别放在try和finally中。     

            代码示例

 public class Test {

	public static void main(String[] args) {
		try {
			int i = 1 / 0;			
		} finally {
			System.out.println("上面报错不影响finally中的输出");
		}
	}
}
/*上面报错不影响finally中的输出
Exception in thread "main" java.lang.ArithmeticException: / by zero
        at Test.main(Test.java:5)
*/

            final, finally, finalize的区别-

            final:修饰类,类不能被继承。修饰方法,方法不能被重写。修饰变量:基本数据类型,值不能被改变;引用数据类型,地址不能被修改(new...),变量值可以修改

            finally:try-catch语句中用的,最后执行的语句。

            finalize:垃圾回收(对象,长时间不适用,垃圾回收。静态变量除外。)。可以显示的调用,但是什么时候回收不由我们决定。

三、异常的体系

               

            Throwable:有两个重要的子类:Error(错误)和Exception(异常)。二者都是java异常处理的重要子类,各种都包含大量子类。

                         Error:用于描述那些无法捕获和处理的错误情况,属于非常严重的错误。(内存溢出,栈溢出)

                        Exception:用于描述那些可以捕获和处理的异常情况,属于不太严重的错误。

                                     RuntimeException:运行时异常,在编译阶段不做检查的一个体系。 

                                     :非运行时异常(受检查异常)

            Throwable类

            toString() 输出该异常的类名。

            getMessage() 输出异常的信息,需要通过构造方法传入异常信息(例如病态信息)。

            printStackTrace() 打印栈信息。

            示例代码

public class Test {
	public static void main(String[] args) {
	Throwable able = new Throwable("异常");
	System.out.println(able.toString()); // 输出该异常的类名
	System.out.println("    ");

	System.out.println(able.getMessage()); // 输出异常的信息
	System.out.println("    ");

	able.printStackTrace(); // 打印栈
	}
}

            java的异常分为可检查的异常和不可检查的异常

            可检查的异常(编译器要求必须处置的异常)

            编译器要求你必须要对这段代码try...catch,或者throws exception,这种异常的特点是java编译器会检查它。

            除了RuntimeException与其子类,以及错误(Error),其他的都是可检查的异常。

四、throws和throw关键字

1.throws

        当程序中发生异常时,无论是程序运行出现的运行时异常,编译阶段的非运行时异常,还是手工抛出的异常,都可以在程序中使用try{}catch进行处理。但也可以在当前的程序(也就是当前方法中),不做任何处理。使用throws关键字在方法声明时,进行异常的抛出,交给方法的调用者去处理。当方法的调用者也不知道如何处理,或不想处理时,可以继续向上抛出。

        格式

         类型   方法名(参数列表) throws  异常列表{  

                  代码

         }

         注:多个异常之间,用英文逗号隔开

         代码示例

public class Test {
	public static void main(String[] args) throws Exception{	
			test01();
	}
	private static void test01() throws FileNotFoundException,IOException{
		InputStream is = new FileInputStream("1.txt");
	}
}

        throws抛出异常

        如果是不可查异常,即Error、RuntimeException或它们的子类,可以不使用throws关键字来声明要抛出的异常。

        必须声明方法可抛出的任何可查异常

        仅当抛出了异常,该方法的调用者才必须处理或者更新抛出该异常。检查异常,如果在方法体上throws,在调用此方法的方法内try-catch,要没在方法体上继续throws,throws到main方法上就到头了。

        调用方法必须遵循任何可减产异常的处理和声明规则。如果catch的异常很多,直接RuntimeException,Exception。

2.throw关键字

        手工抛出异常,其效果和程序抛出异常是一样的,只是它是人为地抛出。

        格式:throw  ThrowableObject

        示例代码

public class Test {
	public static void main(String args[]) {
	System.out.print("Now");
	try {
		System.out.print("is");
		throw new NullPointerException(); // 直接抛出一个异常 ;
		// System.out.print("This will not execute!"); //此句不被执行
	} catch (NullPointerException m) {
		System.out.print("the");
	}
		System.out.print("time. ");
	}
}
//Nowisthetime.

3.throws和throw的区别

        throw是对异常对象的抛出,throws是对异常的声明。

        throw是实实在在地抛出对象,一旦使用throw,一定会产生异常对象,throw只能跟一个异常对象。

        throws后面跟的异常的类名,可以跟多个,使用逗号隔开。

五、自定义异常

        问题:现实中会出现新的病,就需要新的描述。

        分析: Java的面向对象思想将程序中出现的特有问题进行封装。

        当jdk内置异常类型不足以满足系统需求时,我们需要自定义异常类型。

        使用自定义异常和使用jdk内置异常是一回事。

        自定义异常的方式: 继承Exception 或 RuntimeException

        示例代码

//自定义的运行时异常
public class MyException extends RuntimeException{
	/*
	 * 在自定义异常时,完全可以自定义一些属性和方法。但多数时间不需要这样做
	 * */
	public MyException(){
		
	}
	public MyException(String message){
		super(message);
	}
}

        示例代码

// 自定义一个非运行时异常
public class MyException2 extends Exception {
	  public MyException2(){
		  
	  }
      public MyException2(String message){
		  super(message);
	  }
}

        案例:模拟吃饭没带钱的问题

        定义吃饭功能,需要钱。(例如:eat(double money))

        如果钱不够是不能吃饭,有异常。

        自定义NoMoneyException();继承Exception 提供有参无参构造,调用父类有参构造初始化。eat 方法进行判断,小于10块,throw NoMoneyException("钱不够");

        eat 方法进行声明,throws NoMoneyException;

        如果钱不够老板要处理。调用者进行处理。try{}catch(){} 。

class NoMoneyException extends Exception {
	NoMoneyException() {
	}
	NoMoneyException(String message) {
		super(message);
	}
}
class Test {
	public static void main(String[] args) {
		try {
			//eat(0);//跟我干活吧
			// eat(5);//跟我干活吧
			//eat(11);//吃桂林米粉
		} catch (NoMoneyException e) {
			System.out.println("跟我干活吧。");
		}
	}
	public static void eat(double money) throws NoMoneyException {
		if (money < 10) {
			throw new NoMoneyException("钱不够");
		}
		System.out.println("吃桂林米粉");
	}
}

六、注意事项

1.必须在try之后至少添加catch或finally块,也可以都有。

2.必须遵循块顺序:若代码同时使用catch和finall块,则必须将catch块放在try之后。

3.catch块与相应的异常类的类型相关。不用都写Exception。

4.一个try块可能有多个catch。多个catch块异常,应该由子类到父类,或者兄弟之间可以并列,父类放到最后

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值