Java异常

异常

概念:异常是程序在运行期发生的不正常的事件,它会打断指令的正常执行流程。设计良好的程序应该在异常发生时提供处理这些不正常事件的方法,使程序不会因为异常的发生而阻断或产生不可预见的结果。 Java语言使用异常处理机制为程序提供了异常处理的能力。

异常分类

在这里插入图片描述

错误(Error)

JVM系统内部错误或资源耗尽等严重情况,属于JVM需要负担的责任这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。

异常(Exception)

其它因编程错误或偶然的外在因素导致的一般性问题。这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。

Exception异常

其它因编程错误或偶然的外在因素导致的一般性问题。这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。

非受检(unchecked)异常

也叫做运行时异常 RuntimeException):编译器不要求强制处置的异常。一般是指编程时的逻辑错误。是程序员应该积极避免其出现的异常java.lang.RuntimeException及它的子类都是非受检异常:

  • 错误的类型转换:java.lang.ClassCastException
  • 数组下标越界:java.lang.ArrayIndexOutOfBoundsException
  • 下标越界:java.lang.IndexOutOfBoundsException:
  • 空指针访问:java.lang.NullPointerException
  • 算术异常(除0溢出):java.lang.ArithmeticException

错误的类型转换案例:

public class Test01 {
	public static void main(String[] args) {
		Object obj = new Integer(100);
		Double d = (Double) obj;
		System.out.println(d);//ClassCastException - 类型转换异常
	}
}

数组下标越界案例:

public class Test02 {
	public static void main(String[] args) {
		//ArrayIndexOutOfBoundsException - 数组下标越界异常
		int[] arr = {1,2,3};
		System.out.println(arr[10]);
	}
}

下标越界案例:

public class Test03 {
	public static void main(String[] args) {
		//IndexOutOfBoundsException - 下标越界异常
		ArrayList<Object> list = new ArrayList<>();
		System.out.println(list.get(100));
	}
}

空指针访问案例:

public class Test04 {
	public static void main(String[] args) {
		//NullPointerException - 空指针异常
		method(null);
	}
	public static void method(String str){
		System.out.println(str.length());
	}
}

算术异常(除0溢出)案例:

public class Test05 {
	public static void main(String[] args) {
		//ArithmeticException - 算数异常
		System.out.println(10/0);
	}
}

受检(checked)异常

一般性异常:编译器要求必须处置的异常。指的是程序在运行时由于外界因素造成的一般性异常。

  • 解析异常:java.text.ParseException
  • 没有找到指定名称的类:java.lang.ClassNotFoundException
  • 访问不存在的文件:java.io.FileNotFoundException
  • 操作文件时发生的异常:java.io.IOException
  • 操作数据库时发生的异常:java.sql.SQLException

解析异常案例:

public class Test08 {
	public static void main(String[] args) throws ParseException {
		//ParseException - 解析异常
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
		Date date = sdf.parse("2024-5-17");
		System.out.println(date);
	}
}

没有找到指定名称的类案例:

public class Test08 {
	public static void main(String[] args) throws ParseException {
		try {
    		Class<?> clazz = Class.forName("com.example.MyClass");
    	// 类的加载和使用逻辑
		} catch (ClassNotFoundException e) {
   			 e.printStackTrace();
   		// 处理异常,可能需要打印堆栈跟踪信息,并且根据具体情况决定是否重新抛出异常
		}
	}
}

访问不存在的文件案例:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test09 {
        public static void main(String[] args) throws FileNotFoundException {
            // 尝试访问不存在的文件
            FileInputStream fileInputStream = new FileInputStream(new File("test.txt"));       
        }
}

异常处理机制

  1. Java程序在执行过程中如果出现异常,会自动生成一个异常类对象,该异常对象将被自动提交给JVM,这个过程称为抛出throw异常。
  2. 当JVM接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其来进行处理,这一过程称为捕获**(catch)**异常和处理异·常
  3. 如果JVM找不到可以捕获异常的代码,则运行时系统将终止,相应的Java程序也将退出。

throw

​ 异常不仅仅虚拟机可以抛,我们自己也可以抛。我们可以在代码中使用throw关键字(注意不带s)来抛出某个具体的异常对象。很多情况下我们会手动抛出运行时异常。

例如:

throw new RuntimeException("程序出现了异常");

代码实现:

class MyException extends Exception{
	@Override
	public String toString() {
		return "除数不能为0的异常";
	}
}

import java.util.Scanner;
public class Test06 {
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入第一个数字:");
		int a = scan.nextInt();//10
		System.out.println("请输入第二个数字:");
		int b = scan.nextInt();//0
		try {
			method(b);
		} catch (MyException e) {
			b = 1;
		}
		System.out.println(a/b);
		scan.close();
	}
	
	public static void method(int num) throws MyException{
		if(num == 0){
			throw new MyException();
		}
	}
}

throws

​ 在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用出进行处理。

  1. 本身的程序处理不了了,往上一层抛,由上一层去处理
  2. 定义一个方法的时候,通过这种方式来告知调用方,我这个方法有可能会发生异常的。

格式:

public 返回值类型 方法名(参数列表) throws 异常类{

}

代码实现:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test05 {
	public static void main(String[] args){
		try {
			method01();
		} catch (ParseException e) {
			System.out.println("处理异常");
		}
	}
	public static void method01() throws ParseException{
		method02();
	}
	//将该方法里的异常抛给调用方去处理(try...catch 或 继续抛异常)
	//注意:一个方法可以抛出多个异常 
	//public void 方法名() throws 异常1,异常2,异常3....{}
	public static void method02() throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
		Date date = sdf.parse("2024-5-17");
		System.out.println(date);
	}
}

try-catch-finally

格式:

try{
	......	//可能产生异常的代码 
}catch( ExceptionName1 e ){
	......	//异常的处理代码 
}catch( ExceptionName2 e ){
    ...... 	 //异常的处理代码 
} finally{
    ......	 //无论如何都会执行的语句 
}

注意:

  • try 代码段包含的是可能产生异常的代码
  • try 代码段后跟一个或多个catch代码段。(或跟一个finally代码段)
  • JDK新特性,一个catch代码可以可以声明多个能处理的特定异常的类型,多个类型之间用”|”隔开

例如:

catch( ExceptionName1  | ExceptionName2	e){
......	//异常的处理代码 
}
  • 当异常发生时,程序会中止当前的流程去执行相应的catch代码段。
  • 写catch代码时,先捕获的异常的范围不能大于后捕获的异常的范围。大的异常要写在后面finally段的代码无论是否发生异常都执行

代码实现:

import java.util.Scanner;
public class Test03 {
 static void main(String[] args) {
		String[] names = {"胡歌","彭于晏","刘宪华","张根硕"};
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入第一个数字:");
		int a = scan.nextInt();//10
		System.out.println("请输入第二个数字:");
		int b = scan.nextInt();//2
		System.out.println("请输入需要获取元素的下标(0~3):");
		int index = scan.nextInt();//8
		try {
			System.out.println("111");
			System.out.println(a/b);
			System.out.println("222");
			System.out.println(names[index]);
			System.out.println("333");
			//后捕获的异常类型的范围必须大于先捕获的异常类型(父类异常类型捕获的范围比子类大)
			//经验:我们不会去catch运行时异常,一般会catch一般性异常
		}  catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {//捕获算数异常 或 数组下标越界异常
			System.out.println("处理异常...");
		} catch (Exception e) {
		}finally {
			scan.close();
		}	
	}
}
  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值