Java基础篇:异常的处理

异常概述

假设在一个 Java 程序运行期间出现了一个错误。这个错误可能是由于文件包含了错误
信息,或者网络连接出现问题造成的,也有可能是因为使用无效的数组下标, 或者试图使用
一个没有被赋值的对象引用而造成的。用户期望在出现错误时, 程序能够采用一些理智的行
为。——《Java核心技术卷一》

简单来说,异常就是程序出现的错误,有时是程序编写时出现的错误,这是可以避免的,需要我们处理的异常,一种是是系统自身的问题,与我们编写的程序无关,是无法避免的的。Java使用异常的处理机制来处理这些问题。
Java的继承体系:
在这里插入图片描述
所有的异常都是由Throwable演化而来。
异常的分类

error:Java运行时系统内部错误和资源耗尽错误,这个异常我们无法处理,因为不是编写程序的问题。
Exception:在Exception中,分为运行时异常RuntimeException和检查性异常,运行时异常是在程序运行时才会发现的异常,检查性异常在编译期就不能通过,需要立刻处理的异常。
show code :
运行时异常,编译时可以通过。

public class Demo01 {
public static void main(String[] args) {
	int a=1;
	int b=0;
	try {
		System.out.println(a/b);
	} catch (Exception e) {
		System.out.println("除数不能为0");
	}
}
}

运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Demo01.main(Demo01.java:6)

演示一个检查性异常:如果不处理直接就编译不通过。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * demo演示一个编译期异常,就算本身代码没有任何错误,也需要处理的异常。
 */
public class ExceptionDemo03 {
public static void main(String[] args) {
	String s="2020-4-25";
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
	try {
		Date d=sdf.parse(s); 
		System.out.println(d);
	} catch (ParseException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
			
}
}

异常的处理的方案。

第一种处理异常的方案是使用try…catch语句块。
我们把可能发生错误的代码放进catch里面。如果代码发生错误,就转移到catch语句块里面。
查看实例:

package ExceptionDemo;
/*
 * 注意:在trycatch里面,一旦匹配上相应的catch,那么就跳到catch里面执行,然后整个try... catch语句就结束了。
 * 父类是Excption,是万能匹配,但是尽量要具体的类,效率高一点。
 * 在多个catch时,平级的异常谁先谁后无所谓,如果出现了子父类关系,那么父类要放在子类catch的下面。
 */

/*
 * 异常处理方法:
 * A:一个异常就一个trycatch
 * B:多个异常:
 * 			1:写多个try catch
 * 			2:写一个try多个catch
 * 			try{
 * 				.....
 * 					}
 * 			catch(异常类名1 变量名1){}
 * 			catch(异常类名2 变量名2){}
 *			....... 			
 */
public class ExceptionDemo01 {
public static void main(String[] args) {
	
	//method2();
	method3();
	
}

//演示多个异常处理
public static void method3()
{
	try {
		int a=1;
		int b=0;
		System.out.println(a/b);
		
		int [] arr = {1,2,3};
		System.out.println(arr[3]);
		
		String s=null;
		System.out.println(s.length());
	} catch (ArithmeticException e) {
		System.out.println("除数不能为0");
	}catch (ArrayIndexOutOfBoundsException e) {
		System.out.println("数组越界异常");
	}
	catch (NullPointerException e) {
		System.out.println("空指针异常");
	}
	System.out.println("over");
	
}

//两个异常
public static void method2()
{
	try {
		
		int a=1;
		int b=0;
		System.out.println(a/b);
	
	} catch (ArithmeticException e) {
		System.out.println("除数 不能为0");
		} /*
			 * catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组越界异常"); }
			 */
	
	try {
		int [] arr= {1,2,3};
		System.out.println(arr[4]);
	} catch (ArrayIndexOutOfBoundsException e) {
		System.out.println("数字越界异常");
	}
	
	System.out.println("over");
	
}
}

在try…catch语句块中,还有一个是try…catch…finally体系。finally用于释放资源,常用于数据库和Io的操作。
注意:finally语句一定会执行。但是 注意:在虚拟机退出后就不能执行了。(System.exit(0));

showcode:

/*
 * 格式:try ...catch... finally..

 */
public class FinallyDemo01 {

	
	
	public static void main(String[] args) {
		try {
			int a=1;
			int b=0;
			System.out.println(a/b);
		} catch (Exception e) {
			e.printStackTrace();
			//虚拟机退出
			//System.exit(0);
		}
		finally {
			System.out.println("听说finally控制的语句块一定会执行");
		}
		System.out.println("over");
	}
}

结果:
java.lang.ArithmeticException: / by zero
听说finally控制的语句块一定会执行
over
	at finallyDemo.FinallyDemo01.main(FinallyDemo01.java:17)

面试题:如果catch里面有catch语句,那么finally还会不会执行。

  • 如果会,那么是在return前还是return后。
  • 会,前。

演示代码:

public class FinallyDemo02 {
public static void main(String[] args) {
	System.out.println(getInta());
}


public static int getInta()
{
	int a=1;
	try{
		System.out.println(a/0);
		a=20;
		
	}catch (ArithmeticException e) {
		System.out.println("这里是catch");
		a=30;
		return a;
				
	}
	finally{
		a=40;
		System.out.println("这里是finally");
		
	}
	
	
	return a;
}
}

结果:
这里是catch
这里是finally
30

通果System语句来追踪代码执行的步骤。

异常的处理方案二:throws
谁调用,谁处理。如果不处理,就继续在方法上抛出,直到抛给main方法。但是尽量 不要抛给main方法,因为没有处理还是要出错的

  • 格式:
  • 在方法后throws 异常类型
  • 注意:编译期异常抛出,调用者必须处理,并且在方法上throws 。运行时异常方法不强制需要在方法上抛出,调用者可以不用处理,也可以处理。
    查看实例:注意那些需要try…catch,那些需要throws。
public class ExceptionDemo05 {
public static void main(String[] args) {
	
	//对method1方法异常的处理,必须处理,因为是检查性异常。
	try {
		method1();
	} catch (ParseException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	//方法二异常可以处理也可以不处理,不处理也可以通过,虽然会出错。
	method2();
	
}

//编译期异常的抛出
public static  void method1() throws ParseException 
{
	String s="fkhdasf";
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
	
		Date d=sdf.parse(s); 
		System.out.println(d);
}

//运行时异常的抛出.
public static void method2() throws ArithmeticException
{
	int a=1;
	int b=0;
	System.out.println(a/b);
}

}

自定义异常

我们自定义异常很简单,只需要继承就可以了,如果需要写一个运行时异常,那么就继承RunTimeException。如果需要自定义一个检查性异常,就继承Exception.

查看实例:

//定义一个编译期异常
public class MyException01  extends Exception{


	public MyException01()
	{
		
	}
	
	public MyException01(String message)
	{
		super(message);
	}
}

//定义一个运行期异常
class RunTimeExceptionDemo extends RuntimeException{
	public RunTimeExceptionDemo()
	{
		
	}
	public RunTimeExceptionDemo(String message) {
		super(message);
	}
}

测试类:

public class TestMyException {
public static void main(String[] args) {
	//处理自定义的编译期异常,需要处理
	
	try {
		method1();
	} catch (MyException01 e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	//并不必须要处理
	method2();
}
	
	//使用编译期异常,需要在方法上抛出
	public static void method1() throws MyException01
	{
		int a=1;
		int b=0;
		if(b==0)
		{
			throw  new MyException01("除数补不能为0");
		}else 
		{
			System.out.println(a/b);
		}
	}
	
	
	//使用运行时异常,并不需要在方法上出。
	
	public static void method2()
	{
		int a=1;
		int b=0;
		if(b==0)
		{
			throw new RunTimeExceptionDemo();
		}else{
			System.out.println(a/b);
		}
	}
}

自定义异常的注意事项:
-子类重写父类方法时,子类方法必须抛出相同的异常或者父亲异常的子类。
-如果父类抛出了多个异常,子类重写父类时,子类只能抛出相同的异常或者他的子集,子类不能抛出父类没有的异常。
-如果被覆盖的方法没有异常抛出,那么子类方法决不能抛出异常,如果子类方法有异常抛出,那么子类只能try,不能throws.
以上就是简单的关于异常的总结,感谢阅读。
参考:《Java核心基础卷一》
https://www.cnblogs.com/Qian123/p/5715402.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值