由浅到深认识Java语言(27):异常

该文章Github地址:https://github.com/AntonyCheng/java-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】

在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

上一章:由浅到深认识Java语言(26):阶段性练习

39.异常

异常的概念

定义: Java 程序在运行过程中出现的特殊情况,当出现特殊情况时,就需要为不同的情况提供不同的解决方案,以保证程序能够正常运行,即预防异常的状况;

特殊情况指的是用户输入的问题,网络连接的问题,文件未找到的问题等;

这种特殊情况可以在运行时报错时在 Console 控制台内看到;

预防异常示例如下:

package top.sharehome.Bag;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个数字:");
		try {
			int num = sc.nextInt();
			int i = 10;
			int result = i/num;
			System.out.println(result);
		}catch (InputMismatchException e) {
			// TODO: handle exception
			System.out.println("输入的内容不相符");
		}catch (ArithmeticException e) {
			// TODO: handle exception
			System.out.println("不能是零!");
		}
		System.out.println("!!!!!!!");
	}
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

异常的分类

广义分类: 父类:Throwable

  • Error 错误,这是我们不需要解决的,因为没有办法解决;
  • Exception 异常,这是我们应该(必须)解决的;

异常分类:

  • 编译时异常:在编译时出现的异常,即编译无法通过,编译时必须处理异常才能开始运行,所以编译时异常能够绝对杜绝异常情况的出现;

  • 运行时异常:编译可以通过,即在编译时可以不用处理,在运行时出现了异常,需要事后解决,所以运行时异常并不能够得到绝对的避免,所以我们需要掌握一些常用的运行时异常;

    运行时异常属于 RuntimeException 子类;除了运行时异常以外的所有异常都是编译时异常;

常用的运行时异常

  • 空指针异常(java.lang.NullPointerException):

    示例如下:

    package top.sharehome.Bag;
    
    public class Demo {
    	public static void main(String[] args) {
    		String str = null;
    		char[] cs = str.toCharArray();
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 数组下标越界异常(java.lang.ArrayIndexOutOfBoundsException):

    示例如下:

    package top.sharehome.Bag;
    
    public class Demo {
    	public static void main(String[] args) {
    		char[] c = new char[5];
    		System.out.println(c[5]);
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 输入不匹配异常(java.util.InputMismatchException):

    示例如下:

    package top.sharehome.Bag;
    
    import java.util.Scanner;
    
    public class Demo {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		System.out.println("我们应该输入一个数字,但我却要输入一个字母:");
    		int nextInt = sc.nextInt();
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 算数异常(java.lang.ArithmeticException):

    示例如下:

    package top.sharehome.Bag;
    
    public class Demo {
    	public static void main(String[] args) {
    		int num = 1/0;
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 类型转换异常(java.lang.ClassCastException):

    示例如下:

    package top.sharehome.Bag;
    
    public class Demo {
    	public static void main(String[] args) {
    		A a = new B();  //向上转型
    		C c = (C)a;		//向下转型的
    	}
    }
    
    class A{
    	
    }
    
    class B extends A{
    	
    }
    class C extends A{
    	
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

查询其他运行时异常的方法

  1. 在 Eclipse 中使用 Ctrl+Shift+T 调出 Open Type 窗口;

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 在搜索框中输入 Exception ,找到该类;

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 进入类之后,然后使用 Ctrl+T,调出其子类;

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  4. 再在搜索框中搜索 RuntimeException 后进入,若要查询编译时异常,则查询除 RuntimeException 以外的异常即可;

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 进入该子类之后,再次使用 Ctrl+T 即可看到该类中所包含的运行时异常;

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

异常生成机制

抛抓模式

当异常对象被创建并抛出时,程序就会遇到这个异常,遇到异常之后,如果没有任何的处理方法,那么 main 方法碰到异常程序终止,如果遇到异常后有处理方案(try-catch),那么就会去匹配 catch 分支,查看 catch 里的异常类型是否与抛出的异常类型相同,如果相同,就运行该 catch 分支中的语句,就表示该异常被处理,如果所有的 catch 分支都没有与该异常类型匹配,那么该异常还是会来到 main 方法中,然后程序终止;

当异常被处理时,catch 里的异常对象能够获取一些该异常的信息, catch 中的异常对象的常用方法:

  • e.getMessage();
  • e.printStackTrace();

异常的处理方案

示例如下:

以 io 流(后续学习)访问系统内存为例,D: 盘中没有 abc.java 这个文件,我们来访问它;

package top.sharehome.Bag;

import java.io.FileInputStream;

public class Demo {
	public static void main(String[] args) {
		FileInputStream fis = new FileInputStream("d:/abc.java");
	}
}

报错效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里给了我们两个选择,一种是将异常向上抛,一种是 try-catch-finally 处理方式

热处理异常

即使用 try-catch-finally 结构;

  • try-catch-catch-…… 语法:

    我们将可能出现异常的代码语句放入 try 语句中,如果没有出现异常,就按照原计划执行;

    若出现异常就会选择进入后续的 catch 语句,若出现相匹配的异常类型,则执行对应 catch 内容,同时舍弃该 catch 之后的 catch 代码;若没有出现相匹配的异常,该程序就会被系统自动处理,在控制台进行报错;

    示例如下:以输入不匹配异常为例;

    package top.sharehome.Bag;
    
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class Demo {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		System.out.println("输入数字正常执行,非数字异常执行:");
    		try {
    			int num = sc.nextInt();
    			System.out.printf("num = %d",num);
    		} catch (InputMismatchException e) {
                //这里已经找到所匹配的异常,即使下面的 Exception 也满足条件,也不会执行了
    			// TODO: handle exception
    			System.out.println("输入错误!!");
    		}catch (ArrayIndexOutOfBoundsException e) {
    			// TODO: handle exception
    			System.out.println("指针内存溢出!");
    		}catch (NullPointerException e) {
    			// TODO: handle exception
    			System.out.println("空指针异常!");
    		}catch (ArithmeticException e) {
    			// TODO: handle exception
    			System.out.println("计算异常!");
    		}catch (Exception e) {
    			// TODO: handle exception
    			System.out.println("出现异常!");
    		}
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • try-finally 语法:

    finally 后的代码指的是无论出现异常,都必须要执行的代码,在该语法结构中,finally 的优先级甚至大于 return;

    一串正常代码中,一旦遇到 return ,就会终止程序,返回该返回的值,但是在该结构中即使返回了应该返回的值,依然还会执行 finally 中的代码;

    示例如下:

    package top.sharehome.Bag;
    
    public class Demo {
    	public static void main(String[] args) {
    		int num = method();
    		System.out.println("num+num=" + num);
    	}
    
    	public static int method() {
    		try {
    			int num = 10 / 5;
    			return num + num;
    		} finally {
    			// TODO: handle finally clause
    			System.out.println("我必须得执行!");
    		}
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • try-catch-catch-……-finally 语法:

    该结构是以上两种情况的结合;

    示例如下:

    package top.sharehome.Bag;
    
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class Demo {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		System.out.println("输入数字正常执行,非数字异常执行:");
    		try {
    			int num = sc.nextInt();
    			System.out.printf("num = %d",num);
    		} catch (InputMismatchException e) {
                //这里已经找到所匹配的异常,即使下面的 Exception 也满足条件,也不会执行了
    			// TODO: handle exception
    			System.out.println("输入错误!!");
    		}catch (ArrayIndexOutOfBoundsException e) {
    			// TODO: handle exception
    			System.out.println("指针内存溢出!");
    		}catch (NullPointerException e) {
    			// TODO: handle exception
    			System.out.println("空指针异常!");
    		}catch (ArithmeticException e) {
    			// TODO: handle exception
    			System.out.println("计算异常!");
    		}catch (Exception e) {
    			// TODO: handle exception
    			System.out.println("出现异常!");
    		}finally {
    			System.out.println("运行时异常排除完毕!");
    		}
    	}
    }
    

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

冷处理编译时异常

向上抛

先用未能找到文件异常(编译时异常)来引出问题,以 io 流(后续学习)访问系统内存为例,D: 盘中没有 abc.java 这个文件,我们来访问它;

示例如下:

package top.sharehome.Bag;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo {
	public static void main(String[] args) throws FileNotFoundException {
		m1();
	}
	static void m1() throws FileNotFoundException {
		m2();
	}
	static void m2() throws FileNotFoundException {
		m3();
	}
	static void m3() throws FileNotFoundException {
		m4();
	}
	static void m4() throws FileNotFoundException {
		FileInputStream fis = new FileInputStream("d:/abc.java");
	}
}

此时编译时异常就不会出现报错,运行程序若没有出现异常就不会报错,若出现异常就终止程序;

由于该异常申请是从各个方法抛出,直到抛给 main 方法才得以解决,所以称之为向上抛

我们也可以在中途使用热处理将其解决:

package top.sharehome.Bag;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo {
	public static void main(String[] args) {
		m1();
	}

	static void m1() {
		try {
			m2();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	static void m2() throws FileNotFoundException {
		m3();
	}

	static void m3() throws FileNotFoundException {
		m4();
	}

	static void m4() throws FileNotFoundException {
		FileInputStream fis = new FileInputStream("d:/abc.java");
	}
}

此时就结束向上抛异常这样的操作;

自定义异常

**示例如下:**设计一个遇到负数就报错的异常;

NegativeNumberException 类:

package top.sharehome.Bag;

public class NegativeNumberException extends Exception{
	//因为继承的是Exception,所以这里是一个编译时异常
	//如果继承RuntimeException,这里就是一个运行时异常
	//以下代码均是继承后的方法重写代码
	public NegativeNumberException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public NegativeNumberException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public NegativeNumberException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

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

	public NegativeNumberException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}	
}

Demo 类:

package top.sharehome.Bag;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		try {
			int num = sc.nextInt();
            //这里需要判断一下抛出自定义异常的条件和内容
			if (num < 0) {
				throw new NegativeNumberException("该数不能是负数!");
			}
		} catch (InputMismatchException e) {
			System.out.println("输入不匹配;");
		} catch (NegativeNumberException e) {
            // 以下是自定义异常的效果;
			// TODO: handle exception
			String message = e.getMessage();
			System.out.println(message);
		}
	}
}

打印效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下一章:由浅到深认识Java语言(28):集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值