黑马毕向东Java课程笔记(day09-5到9-11):面向对象(第六部分)java异常1—描述

参考文章:
异常描述

1.1、异常概述
  异常:就是程序在运行时出现不正常情况。
  异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并将这些问题封装成对象。其实异常就是java对不正常情况进行描述后的对象体现。

  对于问题的划分:两种:一种是严重的问题,一种非严重的问题。

1)对于严重的,java通过Error类进行描述。Error是程序中无法处理的错误,表示运行应用程序中出现了严重的错误。此类错误一般表示代码运行时JVM出现问题,通常有Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如说当jvm耗完可用内存时,将出现OutOfMemoryError,此类错误发生时,JVM将终止线程。这些错误是不可查的,因此我们事先不需要也没办法专门设计代码去处理此类错误。

2)对与非严重的,java通过Exception类进行描述。对于Exception,程序本身可以捕获并且可以处理的这些异常。

  Exception这种异常又分为两类:运行时异常和编译异常。

1)运行时异常(不受检异常):RuntimeException类及其子类表示JVM在运行期间可能出现的错误。比如说试图使用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理(不处理一样会编译通过)。

2)编译异常(受检异常):Exception中除RuntimeException极其子类之外的异常。如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,否则编译不通过。在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类。

  Exception又可以分为可查异常与不可查异常:java的所有异常可以分为可查异常(checked exception)和不可查异常(unchecked exception)。

1)可查异常(可查既在编译的时候能够被检测出来,那么就算非运行时异常):编译器要求必须处理的异常。正确的程序在运行过程中,经常容易出现的、符合预期的异常情况。一旦发生此类异常,就必须采用某种方式进行处理。除RuntimeException及其子类外,其他的Exception异常都属于可查异常。编译器会检查此类异常,也就是说当编译器检查到应用中的某处可能会此类异常时,将会提示你处理本异常——要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。

2)不可查异常:编译器不会进行检查并且不要求必须处理的异常,也就说当程序中出现此类异常时,即使我们没有try-catch捕获它,也没有使用throws抛出该异常,编译也会正常通过。该类异常包括运行时异常(RuntimeException极其子类)和错误(Error)(需要注意error在编译的时候可以通过,但是运行时无法通过)。(运行不通过)

  无论Error或者Exception都具有一些共性内容,比如:不正常情况的信息,引发原因等。有了共性就可以将Error类与Exception类向上抽取:Throwable类:
在这里插入图片描述

1.2、异常的处理
1.2.1、异常处理机制
  在java应用中,异常的处理机制分为抛出异常和捕获异常。

1)抛出异常:当一个方法出现错误而引发异常时,该方法会将该异常类型以及异常出现时的程序状态信息封装为异常对象,并交给本应用。运行时,该应用将寻找处理异常的代码并执行。任何代码都可以通过throw关键词抛出异常,比如java源代码抛出异常、自己编写的代码抛出异常等。

2)捕获异常:一旦方法抛出异常,系统自动根据该异常对象寻找合适异常处理器(Exception Handler)来处理该异常。所谓合适类型的异常处理器指的是异常对象类型和异常处理器类型一致。

  对于不同的异常,java采用不同的异常处理方式:

1)运行异常将由系统自动抛出,应用本身可以选择处理或者忽略该异常。

2、对于方法中产生的Error,该异常一旦发生JVM将自行处理该异常,因此java允许应用不抛出此类异常。

3、对于所有的可查异常(既会在编译时出错的异常),必须进行捕获或者抛出该方法之外交给上层处理。也就是当一个方法存在异常时,要么使用try-catch捕获,要么使用该方法使用throws将该异常抛调用该方法的上层调用者

1.2.2、异常处理语句
1、try-catch语句

try {
   
	//可能产生的异常的代码区,也成为监控区
	}catch (ExceptionType1 e) {
   
    //捕获并处理try抛出异常类型为ExceptionType1的异常
    }catch(ExceptionType2 e) {
   
    //捕获并处理try抛出异常类型为ExceptionType2的异常
        }

  监控区一旦发生异常,则会根据当前运行时的信息创建异常对象,并将该异常对象抛出监控区,同时系统根据该异常对象依次匹配catch子句,若匹配成功(抛出的异常对象的类型和catch子句的异常类的类型或者是该异常类的子类的类型一致),则运行其中catch代码块中的异常处理代码,一旦处理结束,那就意味着整个try-catch结束。含有多个catch子句,一旦其中一个catch子句与抛出的异常对象类型一致时,其他catch子句将不再有匹配异常对象的机会。
  例子1:

//注意视频9-6的5分钟开始处对异常处理流程的描述
public class ExceptionTest {
   

	public static void main(String[] args) {
   
		Demo d = new Demo();
		
		try
		{
   
			int x = d.div(4, 0);
			System.out.println("x="+x);//try代码块出现异常之后的代码不会被执行,因此出现异常后这句不会执行
		}catch(Exception e)//Exception e = new ArithmeticException();
		//这里创建一个Exception类型的引用变量来保存期子类ArithmeticException的对象
		{
   
			System.out.println(e.getMessage());//获取异常信息。
			System.out.println(e.toString());//获取异常名称:异常信息
			e.printStackTrace();//获取异常名称:异常信息以及异常来源的位置
			//其实jvm默认的异常处理机制,就是在调用printStackTrace方法。该方法打印异常的堆栈的跟踪信息。
		}
		System.out.println("over");
	}
}

class Demo
{
   
	int div(int a,int b)
	{
   
		return a/b;
	}
}

2、try-catch-finally

try {
   
    //可能产生的异常的代码区
   }catch (ExceptionType1 e) {
   
   //捕获并处理try抛出异常类型为ExceptionType1的异常
   }catch (ExceptionType2 e){
   
  //捕获并处理try抛出异常类型为ExceptionType2的异常
   }finally{
   
  //无论是出现异常,finally块中的代码都将被执行
   }

  try-catch-finally的处理过程:
A)try没有捕获异常时,try代码块中的语句依次被执行,跳过catch。如果存在finally则执行finally代码块,否则执行后续代码;
B)try捕获到异常时,如果没有与之匹配的catch子句,则该异常交给JVM处理。如果存在finally,则其中的代码仍然被执行,但是finally之后的代码不会被执行(此时编译出错并由虚拟机在控制台抛出异常,执行完finally之后,代码不会继续执行,下面的部分就交给虚拟机);
对于(try-finally)语句,如果你要在一个功能中定义一些一定会执行的代码,可以将这些代码放到try-finally语句的finally中,就一定会执行!!!
C)try捕获到异常时,如果存在与之匹配的catch,则跳到该catch代码块执行处理。如果存在finally则执行finally代码块,执行完finally代码块之后继续执行try-catch-finally块之后的代码;
  记住一点:catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明(在方法外throws),否则编译不通过。
另外注意,try代码块出现异常之后的代码不会被执行。(见下图:)
在这里插入图片描述
  总结
try代码块:用于捕获异常。其后可以接零个或者多个catch块。如果没有catch块,后必须跟finally块,来完成资源释放等操作,另外建议不要在finally中使用return,不用尝试通过catch来控制代码流程。

catch代码块:用于捕获异常,并在其中处理异常。

finally代码块:无论是否捕获异常,finally代码总会被执行。**如果try代码块或者catch代码块中有return语句时,finally代码块将在方法返回前被执行。**注意以下几种情况,finally代码块不会被执行:
1、 在前边的代码中使用System.exit(0)退出应用,系统退出,jvm虚拟机结束;
2、 程序所在的线程死亡或者cpu关闭;
3、 如果在finally代码块中的操作又产生异常,则该finally代码块不能完全执行结束,同时该异常会覆盖前边抛出的异常。
  例子1:

/*
finally代码块:定义一定执行的代码,通常用于关闭资源。
 */
//自定义一个负数异常
class FuShuException extends Exception
{
   
	FuShuException(String msg)
	{
   
		super(msg);
	}
}

class Demo
{
   
	int div(int a,int b)throws FuShuException
	{
   
		if(b<0)
			throw new FuShuException("除数为负数");
		return a/b;
	}
}

public class ExceptionTest {
   

	public static void main(String[] args) 
	{
    
		Demo d = new Demo();
		try
		{
   
			int x = d.div(4,-1);
			System.out.println("x="+x);
		}
		catch(FuShuException e)
		{
   
			System.out.println(e.toString());
			//如果出现异常我们希望程序结束,直接返回,这样finally还是会执行,但是System.out.println("over");不会执行
			
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值