异常处理和递归

本文深入探讨了Java中的异常处理机制,包括异常的体系结构、处理方式、自定义异常及异常分类。同时,详细讲解了递归的概念、实现及注意事项,通过具体案例帮助理解。

一、异常处理
1.异常的概述和体系结构
异常的概述:异常,即不正常,我们的代码出现了编译或者运行时的错误;异常包含了错误的类型、原因以及位置。
举例:

package test;

public class test {	
	public static void main(String[] args) {
		int a = 10/0;
	}	
}

出现异常:
在这里插入图片描述
异常的体系结构
  Throwable(异常类最顶层,Object类不算)
    Exception:可以处理的问题;
    Error:出现的不能够处理的问题;

举例:
  电脑系统中毒:重装系统就可以了(为Exception);
  电脑主板坏了:买一台新电脑(为Error)。

继承关系如下:
在这里插入图片描述
2.异常处理方式
1)jvm处理异常方式:
如果出现异常,我们没有处理,则jvm会处理,会将异常的类型、原因以及位置显示在命令行;并且终止程序,异常代码后面的代码将不再执行。
2)自定义处理异常方式:
捕获处理

	public static void main(String[] args) {
		try {
			System.out.println(1);
			System.out.println(10/0);
			System.out.println(2);
		} 
		catch(ArithmeticException ae) {
			System.out.println("除数不能为0");
		}
		
		System.out.println(3);

	}	

try…catch的执行顺序:首先执行try语句,如果发现异常,异常下面的代码不再执行,直接跳入catch语句,catch语句结束后,整个try…catch语句结束;如果没有发现异常,try语句执行结束后,try…catch语句直接结束,不再执行catch语句。

try…catch语句执行机理:虚拟机捕获的异常与catch中的异常类型进行比较,若一致,则执行catch的内容。

抛出处理:抛出异常即将异常抛出,抛给调用此方法的对象处理,若主函数调用此方法,则主函数也要抛出异常给虚拟机处理。

import java.io.FileWriter;
public class test {	
	public static void main(String[] args) throws Exception{
		function();
	}	
	
	public static void function() throws Exception{
		FileWriter fw = new FileWriter("a.txt");
	}
}

3)处理多个异常:
处理多个异常:使用多个try…catch语句来捕获多个异常;

	public static void main(String[] args) {
		try {
			System.out.println(10/0);
		}
		catch(ArithmeticException ae) {
			System.out.println("出现除0异常");
		}
		try {
			int arr[] = new int[5];
			System.out.println(arr[8]);
		}
        catch(ArrayIndexOutOfBoundsException ae) {
        	System.out.println("出现数组越界异常");
        }
	}	

处理多种类异常:使用一个try和多个catch来捕获异常;
注:多个catch之间可以有子父类的关系,平级之间没有顺序关系,如果有子父类等级关系,父类异常必须放在后面;

	public static void main(String[] args) {
		try {
			int arr[] = new int[5];
			System.out.println(arr[8]);
			System.out.println(10/0);
		}
		catch(ArithmeticException ae) {
			System.out.println("出现除0异常");
		}
        catch(ArrayIndexOutOfBoundsException ae) {
        	System.out.println("出现数组越界异常");
        }
		catch(Exception ae) {
			System.out.println("出现异常了");
		}
	}	

4)Throwable的常用方法:
String getMessage():异常出现原因;
String toString():异常出现的类型+原因;
void printStackTrace():异常出现的类型+原因+位置。

	public static void main(String[] args) {
		try {
			System.out.println(10/0);
		}
		catch(ArithmeticException ae) {
			//System.out.println(ae.getMessage());
			//System.out.println(ae.toString());
			ae.printStackTrace();
		}
	}	

运行结果:
在这里插入图片描述
5)finally的概述和应用场景:
finally简述:组合try…catch使用,用于资源释放等收尾工作,无论try…catch语句如何执行,finally代码一定会执行。
格式:
try{
  有可能出现问题的代码;
}
catch{
  处理异常;
}
finally{
  释放资源;
  清理垃圾;
}

6)异常的分类:
运行时期异常:RuntimeException的子类就是运行时期的异常,在编译时期可以自由选择处理或者不处理;
编译时期异常:是Exception的子类,非RuntimeException的子类,在编译时期必须处理。

3.自定义异常
如何定义一个异常类:非常简单,写一个类去继承Exception或者RuntimeException,然后实现多个构造即可。
我们自定义的异常类(有两种定义方式,一种是继承RuntimeException,另一种是继承Exception)如下所示:

public class MyException extends RuntimeException{   //继承RuntimeException,为运行时异常,若继承Exception为编译时异常

	public MyException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}   
}

使用自定义的异常:

public class test {	
	public static void main(String[] args) {
		try {
			checkScore(110);
		}
		catch(Exception e) {
			e.printStackTrace();
		}

	}	
	public static void checkScore(int score) {
		if(score < 0 || score > 100) {
			//throw new RuntimeException("考试成绩不符合要求");
			//throw new Exception("考试成绩不符合要求");   此时在方法后面加上throws Exception
			throw new MyException("考试成绩不符合要求");
		}
		System.out.println("考试成绩符合要求");
	}
}

运行结果:
在这里插入图片描述
注意:如果制造(throw)的是编译时期异常,必须在方法声明出抛出(throws)

二、递归
递归:把大问题拆成很多小问题,再把小问题拆成小问题,…,随着小问题的解决,大问题也随之解决;
实现:在方法的本身不断地调用方法本身;
递归注意事项:
  递归一定要有出口,否则内存溢出;
  递归次数不宜过多,否则内存溢出。

public int jc(int n) {
    if(n == 1){   //为递归出口
        return 1;
    }
    else {
        return n*jc(n-1);
    }
}

递归内存图解:当jc(n=1)执行后,弹出栈,将结果返回到jc(2)方法中,jc(2)执行后弹出栈…,最后将jc(5)的结果赋值给result,程序结束。
在这里插入图片描述
斐波那契数列
古典问题:有一对兔子,出生后第三个月起,每个月都生一对兔子,小兔子长到第三个月后,每个月又生一对兔子,假如兔子都不死,问20个月后有多少只兔子?
分析:到第四个月时,为之前的第二个月生的兔子的第三个月,该兔子可以生兔子(可认为是复制),以此类推,除了第一、二两个月(这两个月可以作为递归程序出口),后面的月份兔子总数为前两个月之和:
第一个月:1
第二个月:1
第三个月:2
第四个月:3
第五个月:5
第六个月:8

public static int method(int n){
    if(n == 1){
        return 1;
    }
    else if(n == 2){
        return 1;
    }
    else {
        return method(n-1)+method(n-2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值