26、Java面向对象——异常

目录

课前先导

一、异常

 1、异常的含义

二、Throwable类

三、 Error类和Exceptio类

1、Error类 

2、Exception类

3、RuntimeException类

 4、异常体系

四、异常处理机制

1、Jvm的默认处理方案 

2、使用try-catch处理异常

3、Throwable中的成员方法 

 4、使用try-catch-finally处理异常

5、使用throws声明异常 

 6、使用throw手动抛出异常

7、 自定义异常

 五、常见异常类


课前先导

今天学习完后,我们Java面向对象的学习就算是结束了。我们下一阶段的学习:

我们先自己思考一下什么是异常?

异常:不正常的。

那它算是错误吗?应该不算,不正常只是和正常有点差别,是夹在错误和正常之间的。

一、异常

我们先来看一个案例:

定义一个数组,通过控制台输入数组下标来获取数组元素

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		int index = input.nextInt();
		System.out.println(num[index]);
	}

}

 在我们输入5的时候,程序运行出错了,因为我们定义的数组中没有下标为5的元素,数组也没那么长。

这里控制台上输出了一个java.lang包下的一个类:ArrayIndexOutOfBoundsException;这个类的意思就是:用非法索引访问数组时抛出的异常。

我们可以用我们学过的方法去解决它;if-else结构;但会存在一个瑕疵,就是我们要添加很多代码,很容易造成代码臃肿。下面我们就学习异常的解决办法。

 1、异常的含义

(1)异常是指在程序的运行过程中发生的不正常事件,如所需文件找不到、网络连接不通或连接中断、算术运算出错(如被零除)、数组下标越界、装载一个不存在的类、对null对象操作、类型转换异常;

(2)异常会中断正在运行的程序(抛出异常的代码,后面的程序不会运行);

(3) 可以通过增加if-else语句对各种异常情况进行判断处理,但有很多缺点:

* 代码臃肿,加入了大量的异常情况判断和处理代码;

程序员把相当多的精力放在了异常处理代码上,放在了“堵漏洞”上,占用了编写业务代码的时间,必然影响开发效率;

很难防止所有的异常,程序仍旧不健壮;

异常处理代码和业务代码交织在一起,影响代码的可读性,加大日后程序的维护难度。

(4) Java提供了异常处理机制,可以由系统来处理程序在运行过程中可能出现的异常事件,使程序员有更多精力关注于业务代码的编写。

二、Throwable类

英文单词:throwable  可抛出、可测试 ;   error   错误 ;  exception  例外的事物

1、Java中有很多类型类型的异常,异常在java.lang包先被封装成了各种异常类;

2、Throwable类是Java语言中所有错误或异常的超类(父类),只有当对象是此类(或其子类之一)的实例时,才能通过Java虚拟机或者Java  throw语句抛出。类似地,只有此类或其子类之一才可以是catch子句中的参数类型。

3、Throwable类有两个直接已知子类:Error类Exception类; 通常用于指示发生了异常情况。

三、 Error类和Exceptio类

我们平常编程会遇到两种两种错误:第一种就是我们在编码期间就报错的错误,我们必须修改好后程序才能启动,这就是Exception异常;第二种是我们编码期间不报错,运行报错,然后我们回来修改代码的错误(编程参数给错,运行结果不是想要的不算),这就是RuntimeException类异常。

还有一个Error类错误是我们无能为力的,这种异常我们是不处理的,比如你的电脑硬件或内存资源不足等问题。

1、Error类 

Error是Throwable的子类,用于指示合理的应用程序不应该捕获的严重问题。大多数这样的错误都是异常条件。虽然ThreadDeath错误是一个“正规”的条件,但它也是Error的子类,因为大多数应用程序都不应该试图捕获它。

在执行该方法期间,无需在其throws子句中声明可能抛出但是未能捕获的Error的任何子类,因为这些错误可能是再也不会发生的异常条件。

2、Exception类

Exception类及其子类是Throwable的一种形式,它指出了合理的应用程序想要捕获的条件。

3、RuntimeException类

RuntimeException类是Exception类的子类,RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常超类。可能在执行方法期间抛出但未捕获的RuntimeException的任何子类都无需再throws子句中进行声明。

 4、异常体系

Error:严重问题,不需要处理;

Exception:异常类,程序本身可以处理的问题:

--->RuntimeException:在编译期间是不检查的,出现问题后,需要我们回来修改代码;

---> 非RuntimeException:在编译期间就必须处理,否则程序不能通过编译,就更不能正常运行了。

四、异常处理机制

异常一般我们是检查不出来的,总是在运行时报异常,所以我们要对异常进行预防。 

在程序执行代码时,若发生了异常,程序会按照预定的处理办法对异常进行处理,异常处理完毕之后,程序继续运行。

Java的异常处理是通过五个关键字来实现的:

try  、  catch  、  finally   、  throw   、  throws

1、Jvm的默认处理方案 

我们先来看一下出现异常时,Java虚拟机会怎么自己处理。

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		int index = input.nextInt();
		System.out.println(num[index]);
		
		System.out.println("程序结束");
	}

}

在控制台输出了异常的类名和异常的原因:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 

还有异常出现的位置:at com.oracle.java03.Demo26.main(Demo26.java:12)

异常后面的代码并未运行。

 如果程序出现了问题,我们没有做出任何处理,最后JVM会做默认的处理:

--->把异常的名称、异常的原因以及异常出现的位置等信息输出在了控制台;

--->程序停止执行。

2、使用try-catch处理异常

(1)语法格式:

try{
            
可能出现异常的代码
        }catch(异常类名 变量名){
          
 异常的处理代码
        }

(2)执行流程

程序从try里面的代码开始执行

出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java的运行时系统

当Java运行时系统接收到异常对象时(变量名接收的对象,变量名就是对象名),会到catch中去找匹配的异常类,找到后进行异常的处理;执行完毕后,程序还可以继续往下执行

(3)代码演示

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]); //这里出现异常,会产生一个异常对象
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("你访问的数组索引不存在");
		}
		
		System.out.println("程序结束");
	}

}

(4)多重catch处理异常 

---> 一段代码可能会引发多种类型的异常,这时,可以在一个try语句块后面跟多个catch语句块分别处理不同的异常。但排列顺序必须是从子类到父类,最后一个一般都是Exception类;

---> 按照匹配原则,如果把父类异常放到前面,后面的catch语句块将不会有被执行机会;

---> 运行时,系统从上到下分别对每个catch语句块处理的异常类型进行检测,并执行第一个与异常类型匹配的catch语句。执行其中的一条catch语句之后,其后的catch语句将被忽略。

3、Throwable中的成员方法 

我们在上面的代码中,异常处理代码给的是一个输出语句,这个不太标准。

代码产生了异常类的对象,我们通过异常类的对象来调用异常类中的方法:

Throwable是所有错误和异常的祖宗类, 只要属于这个体系的,都可以使用它的成员方法。

 (1)getMessage()方法

出现异常的原因

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]);
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.getMessage());
		}
		
		System.out.println("程序结束");
	}

}

 (2)toString()方法

异常的类名以及异常的原因

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]);
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.toString());
		}
		
		System.out.println("程序结束");
	}

}

 (3)printStackTrace()方法

异常的类名,异常的原因,异常的信息

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]);
		}catch(ArrayIndexOutOfBoundsException e){
			e.printStackTrace();
		}
		
		System.out.println("程序结束");
	}

}

 4、使用try-catch-finally处理异常

积极认错,坚决不改!!!

try代码块中选择的是我们认为可能出现异常的代码,只要出现一处异常,其他的代码也不会执行,如果仍然想执行try{}代码块中的语句 ,可以用finally代码块实现。

(1) 如果希望try语句块中不管是否发生异常,都执行某些代码,那么就需要在try-catch语句块中加入finally语句块,把要执行的语句放入finally语句块中;

(2)无论是否发生异常,finally语句块中的代码总能被执行;

(3)try-catch-finally结构中的try语句是必须存在的,catch、finally语句为可选,但是两者至少出现其中之一;

(4)如果在try语句块或者catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出;

(5)finally代码块中的语句不执行的唯一情况:在try代码块或catch代码块中执行了System.exit(非0数字)退出Java虚拟机的语句。

语法格式一:

 try{
          
 //可能出现异常的代码
        }catch(异常类名 变量名){
          
 //异常处理代码
        }finally{
         
   //想要执行的代码
        }

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]);
			System.out.println("积极认错,坚决不改");
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.toString());
		}finally{
			System.out.println("积极认错,坚决不改");
		}
		
		System.out.println("程序结束");
	}

}

语法格式二: 

try{
          
 //可能出现异常的代码
        }finally{
          
 //想要执行的代码
        }

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		int[] num = {1,2,3,4,5};
		System.out.print("请输入你要差看的元素下标:");
		
		Scanner input = new Scanner(System.in);
		
		try{
			int index = input.nextInt();
			System.out.println(num[index]);
			System.out.println("积极认错,坚决不改");
		}finally{
			System.out.println("积极认错,坚决不改");
		}
		
		System.out.println("程序结束");
	}

}

 第二种语法并没有把语句执行完,发生异常就停止执行了,但依然执行了finally里面的代码。

5、使用throws声明异常 

甩锅达人throws

throws是跟在方法名的括号后面,代码有异常不处理,就抛出来,然后谁用这个方法,谁用try-catch解决 

(1)语法格式: 

throws  异常类名1,异常类名2,.......,异常类名n

(2)throws的用法

---> 如果在一个方法体中抛出了异常,并希望调用者能够及时地捕获异常,Java语言中通过关键字throws声明某个方法可能抛出的各种异常以通知调用者 ;

--->throws可以同时声明多个异常,之间由逗号隔开;

--->声明异常是在方法的参数列表后面声明。

(3) 调用声明异常方法的两种处理方式

(1)使用try-catch捕获并处理异常;

(2)通过throws继续声明异常。如果调用者不知道如何处理该异常,可以继续通过throws声明异常,让上一级调用者处理异常。

main()方法声明的异常由Java虚拟机来处理

(4)代码演示 

使用throws只是声明了异常,并没有处理 

public class Demo26 {
	//main方法
	public static void main(String[] args) {
		System.out.println("程序开始");
		try{
			method();
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.getMessage());
		}
		System.out.println("程序结束");
	}
	
	//定义方法
	public static void method() throws ArrayIndexOutOfBoundsException{
		int[] arr = {1,2,3,4,5};
		System.out.println(arr[5]);
	}
	
	
}

 6、使用throw手动抛出异常

我说你有病你就有病

除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,比如年龄不再正常范围内,性别输入不是“男”或者“女”等,此时需要程序员而不是系统来自行抛出异常,把问题提交给调用者去解决。 

(1)语法格式:

throw new  异常类名(参数)

(2)代码演示

import java.util.Scanner;

public class Demo26 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		
		int[] arr = {1,2,3,4,5};
		System.out.println("请输入你要查询的数组元素下标:");
		int index = input.nextInt();
		
		if(index < 0 || index > arr.length){
			throw new ArrayIndexOutOfBoundsException("越界了");
		}else{
			System.out.println(arr[index]);
		}
	}
}

 (3)throw和throws的区别

--->作用不同:throw用于程序自行产生并抛出异常;throws用于声明该方法内抛出了异常;

--->位置不同:throw位于方法内部,可以作为单独语句使用;throws必须跟在方法参数列表后面,不能单独使用;

--->内容不同:throw抛出一个异常表示对象,只能是一个;throws后面跟异常类,可以跟多个

7、 自定义异常

当JDK中的异常类型不能满足程序的需要时,可以自定义异常类。

(1)创建一个类,继承Exception类或RuntimeException类;

(2)定义无参构造方法和有参构造方法;

(3)实例化自定义对象。

创建自定义异常类,继承Exception类 

public class CustomException extends Exception {
	
	public CustomException(){
		super();
	}
	
	public CustomException(String message){
		super(message);
	}
	
	public CustomException(String message, Throwable cause){
		super(message,cause);
	}
	
	public CustomException(Throwable cause){
		super(cause);
	}

}

创建实现类Arr

给方法用throws声明有我们自定义异常类的异常

在方法中给判断,产生异常时我们用throw去抛

public class Arr {
	
	public void method(int index) throws CustomException{
		int[] arr = {1,2,3,4,5};
		if(index < 0 || index > 4){
			throw new CustomException("越界了");
		}else{
			System.out.println(arr[index]);
		}
		
	}

}

创建测试类

因为我们在Arr类中用throws抛出了CustomException类的异常,所有调用方法时要用try-catch解决,否则会报错

import java.util.Scanner;

public class Test {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.println("请输入你要查询的数组元素下标:");
		int index = input.nextInt();
		
		Arr arr = new Arr();
		try {
			arr.method(index);
		} catch (CustomException e) {
			e.printStackTrace();
		}
	}

}

 五、常见异常类

关于异常的学习虽然内容很多,不过大家暂时不需要深入学习,感觉一天学习不了那么多内容的小伙伴也不要着急,可以把一天的内容分几天学也是可以的,没必要在别人觉得你很颓废的时候去赶进度;学习速度快的小伙伴也要保持谦卑。

要有耐性,不要操之过急。越是心平气和,越有成绩,时时刻刻要承认自己是笨伯,不怕做笨功夫,那就不会期待太切,稍不进步就慌乱了。

今天到此结束,我是一米八、有腹肌、低于半小时你报警的Loveletter,觉得内容不错的小伙伴可以点点关注,我们下篇博文见,再见!

 

最近更新了个新的栏目:MySQL数据库管理系统,有兴趣的小伙伴可以去看一下,给作者提一下建议http://t.csdn.cn/Syf9E 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值