在我们编写程序的过程和编译运行程序的时候都不能保证我们的程序永远不会出错,Java程序运行过程中所发生的异常事件可分为两类:
错误(Error):JVM系统内部错误,资源耗尽严重情况。
异常(Exception):其它编程错误或偶然的外在因素导致的一致性问题,例如:
对负数开平方根
空指针访问NullPointerExcetion
试图读取不存在文件FileNotFonundException
网络连接中断
程序中导致程序中断的一些情况叫做异常,一般程序员可以处理。
处理异常的两种方式:throws和try…catch…finally
try快的功能和规则:try块内部一般写编程人员可能会出现的异常代码,使程序运行不会因为出现异常而中断。
catch块的功能和规则:
功能:可以截取声明的异常,并在语句块内对其进行处理;
规则:
catch(Exception e){
System.out.println("this is an Exception!"):
}
finally块的功能和规则:
finally块一般写一些不论是否发生异常都必须执行一次的代码,例如关闭与数据库的连接等。
throw和throws的功能和使用方法:
throw指编程人员主动抛出一个异常:throw new NullPointerException();
throws指程序遇到异常情况的被动抛出一个异常:public void test() throws Exception()。
什么是预定义异常?
java程序中预先定义好的异常就叫做预定义异常。
1.异常: 就是程序中不正常的现象(错误和异常)
2. 异常的体系结构
Throwable
Error:☞ 程序员不能处理的情况,需要修改底层源代码
Exception : ☞ 需要程序员处理的情况
☞RuntimeException :在运行阶段出现的问题
☞编译异常 :在编译阶段出现的问题
3. 异常处理的2种方式
自己解决: try...catch ... finally
别人解决: throws
4. 创建异常对象
new 异常类("错误信息");
抛出异常对象
throw new 异常类("错误信息");
5. 注意事项
1> 运行时异常被抛出可以不处理,因为JVM会处理
2> 如果父类抛出了异常,子类覆盖父类的方法时 只能有3种选择
第1种:不抛出任何异常
第2种:抛出和父类方法一样的异常
第3种:抛出和父类方法一样的异常的子异常
3> 一个try可以匹配多个catch,若catch的异常类之间存在继承关系 则子类异常必须在父类异常的前面
1> String getMessage() 返回异常信息 / by zero
2> void printStackTrace() 使用红色字体打印错误信息(异常名称,错误信息,位置) java.lang.ArithmeticException: / by zero at com.override.Demo.main(Demo.java:7)
3> String toString() 使用简短的字符串描述错误 java.lang.ArithmeticException: / by zero 1234567
异常: 指程序在编译、运行期间发生了某种异(xxxxxxxException),我们可以对异常进行具体的处理, 若不处理程序就会结束运行。
错误: 指程序在运行期间发生了某种错误(XXXXXError),Error错误通常没有具体的处理方式 程序将会结束运行,Error错误发生往往是系统级别的问题例如JVM所在系统发生的 并且反馈给JVM,我们无法针对处理,只能修改代码。
jdk运行: A.java -----编译器javac.exe编译------> A.class -------解释器java.exe运行------> 机器码
编译时检查异常: 在编译阶段就会出现的异常
运行时异常(RuntimeException): RuntimeException及其它的子类,可以通过编译,但是在运行 的时候出现的异常
在编写程序时,我们必须要考虑程序出现问题的情况。
例如: 在定义方法时,方法需要接收参数,那么当调用方法时, 需要给方法的参数赋值, 首先需要对参数进行合法的判断, 若数据不合法,就应该告诉告诉调用者,你传递的参数是错误的 需要传递合法的参数,这时可以通过抛出异常的方式告诉他。
抛出异常“对象”
作用:可以使用 throw 关键字,在指定的方法中抛出指定的异常对象
格式:throw new XXXXXException("填写异常产生的原因");
注意:① throw 关键字 必须写在方法的内部
② throw 关键字 后面 new 对象必须是 Exception 或者 Exception的子类
③ throw 关键字
情况1: 抛出的是 检查异常,则我们必须处理这个异常
throw new Exception("异常的原因");
//我们必须要手动处理这个异常,
//处理异常有两种: 不负责任 throws往外抛
// 负责任 try...catch
情况2: 抛出的是运行时异常(RuntimeException 或者 RuntimeException的子类) 我们可以不处理,默认交给JVM处理(打印错误信息,中断程序)
捕获: java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定的方式处理 。
格式:
try{
// 可能产生异常的代码(没有异常的代码也可以定义在try中)
// try块中,一旦出现异常,则抛出异常的那句代码后面的代码都不执行啦
// 疑似病人(可能有病,或者没有病)
}catch(异常类名 变量名){
// 数据类型,必须是Exception或者Exception的子类
// 新冠病 ,匹配这个,才会执行这个代码,就会进隔离区
//异常的处理语句,抓取到 和 异常类名一样的的对象才执行
}catch(异常类名2 变量名){
// 普通流感 ,匹配这个,才会执行这个代码
}finally{
//不论是否有异常,finally中内容都会执行(执行1遍)
//不论是有病还是没病,都会从新检测指标
}
System.out.println(“1**”); //以下的代码就可以正常的执行啦
注意:
1> 若多个catch的异常类之间没有继承关系,则顺序随便
2> 若多个catch的异常类之间有继承关系,则 子类异常必须在父类异常的上面
<1> try...catch....finally
<2> try...catch
对代码进行异常检查,并对检测到异常对象,传递给catch,并对异常进行处理
public void m(){
try{
throw new Exception("错误原因");
}catch(Exception e){
e.printStackTrace(); //打印错误信息
}
}
<3> 一个 try 和多个 catch
public void m(){
try{throw new Exception("错误原因");
}catch(xxxxxException e){
}catch(yyyyyException e){
}catch(zzzzzzException e){
}
}
//注意: 若多个catch都没有匹配到异常对象,则抛出JVM处理
// catch的异常类有继承关系,子类异常定义在父类异常的上面
<4> try....finally组合
public void show() throws Exception{
try{
throw new Exception();
}finally{ //不论是否有异常都会执行 } }
作用: 当方法内部抛出异常对象的时候,我们必须处理这个异常对象可以使用throws 抛出异常
抛给谁? 抛给方法的调用者处理(自己不处理,给别人处理)
如果到了main方法,还继续往外抛出,则 最终交给JVM(1.打印错误信息 2.中断程序)
格式:
public 返回值类型 方法名(参数列表) throws aaaaaaaException,bbbbbbException{
// throw new AaaaaException(“产生原因”);
// throw new BbbbbException(“产生原因”);
}
注意: throws 关键字 必须写在方法的声明处
throws 关键字 后面必须是 Exception 或者 Exception 子类
方法内部如果抛出了多个异常对象,那么 throws 后面也必须声明多个异常对象
如果抛出多个异常对象存在父子关系,那么直接抛出父异常就可以
或者选择不声明任何异常。
父类的方法没有抛出异常,子类重写父类的方法时也不要抛出异常,若子类产生了检查异常,则自己在方法内部try…catch处理,不要抛出若子类产生了运行时异常,则不用处理,因为JVM会处理。
重写父类异常可以选择:
选择1: 不抛
选择2: 和父类抛出一样的异常 AException
选择3: 父类异常的子类异常 BException
就是不能抛出父类异常的父异常,和其他异常
throw 定义在方法内部,后面跟的是异常对象
new 异常类构造函数(参数值);
同时只能抛出一个异常对象,抛出异常对象后面的代码不执行
throw new XXXXXException(“异常原因”);
throws 定义在方法的声明上,后面跟的是异常类型
后面可以跟上多个异常类型
public static 返回值类型 方法名(参数列表) throws XXXXException,XXXXXException{ }
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
//null和[]的区别
System.out.println(args.length);
//遍历字符串数组args
System.out.println(Arrays.toString(args));
//访问数组的第一个元素
System.out.println(args[0]);
System.out.println(args[1]);
System.out.println(args[2]);
}
}
import java.util.Scanner;
public class ExceptionExam4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入整数a:");
int a = sc.nextInt();
System.out.println("请输入整数b:");
int b = sc.nextInt();
try {
// ArithmeticException算数异常
System.out.println("---1----");
System.out.println(a / b);// 底层JVA创建一个异常对象,抛出异常
System.out.println("---2----");
} catch (Exception e) {
System.out.println("");
// 获取引起异常的原因/ by zero
String s1 = e.getMessage();
System.out.println(s1);
// 获取异常名称加原因java.lang.ArithmeticException: / by zero
String s2 = e.toString();
System.out.println(s2);
// 使用红色字体输出:异常名称 原因 位置
/*
* java.lang.ArithmeticException: / by zero at
* com.javase18.ExceptionExam4.main(ExceptionExam4.java:16)
*/
e.printStackTrace();
}finally{
sc.close();//无论是否有异常都会执行
}
System.out.println("计算完毕");
}
}
import java.io.File;//文件或者目录
import java.io.FileNotFoundException;
public class RideFile {
//(声明方法需要处理的异常类型)
public static void readFile(String path) throws FileNotFoundException {
System.out.println("1、检查path路径是否存在");
File file = new File(path);
if (file.canExecute()) {
System.out.println("2、读取文件内容");
} else {
// 动作,抛出异常对象
throw new FileNotFoundException("错误原因:参数对应的文件不存在。");//抛出异常对象
}
// 问题的解决方法
// 自己在方法中,使用try...catch...finally 调用方法的对象不用处理
// 抛出throws,谁调用这个方法谁处理这个异常
}
public static void main(String[] args) {
//捕获异常,处理异常
try {
String path = "";
System.out.println("准备读取的文件路径:");
RideFile.readFile(path);// 到了main方法,就不要继续抛出异常
System.out.println("文件读完!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Tests {
public static void main(String[] args) {
try {
Object[] arr = new String[2];
arr[0] = new Integer(10);
}catch(ArrayStoreException e) {
e.printStackTrace();
}
}
//java.lang.ArrayStoreException: java.lang.Integer
at com.javase18.Tests.main(Tests.java:7)
}
class Dog extends Object {
}
class Cat extends Object {
}
public class ExceptionExam6 {
public static void main(String[] args) {
try {
Object[] arr = new Dog[2];
// 只能存储Dog对象或者Dog的子类对象
// ArraysStoreException数组存储异常
arr[0] = new Cat();
// ClassCateException数据类型转换异常
Object ob = new Cat();
Dog dog = (Dog) ob;
} catch (Exception e) {
e.printStackTrace();
}
}
//java.lang.ArrayStoreException: com.javase18.Cat
at com.javase18.ExceptionExam6.main(ExceptionExam6.java:18)
}
import java.time.DateTimeException;
import java.time.LocalDate;
public class Tests {
public static void main(String[] args) {
try {
LocalDate now = LocalDate.of(2020, 13, 10);//参数值必须符合月或者日期的范围
System. out . println(now);
}catch(DateTimeException e) {
e. printStackTrace();
}
}
/*java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 13
at java.time.temporal.ValueRange.checkValidValue(Unknown Source)
at java.time.temporal.ChronoField.checkValidValue(Unknown Source)
at java.time.LocalDate.of(Unknown Source)
at com.javase18.Tests.main(Tests.java:10)*/
}
public class Tests {
public static void main(String[] args) {
// 例如:将字符串转换为其中一个数字类型,但该字符串不具有相应的格式
try {
String str1 = "9.991";
int num = Integer.parseInt(str1);
System.out.println(num);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
/*java.lang.NumberFormatException: For input string: "9.991"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at com.javase18.Tests.main(Tests.java:12)*/
}
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
try {
//null和[]的区别
System.out.println(args.length);
//遍历字符串数组args
System.out.println(Arrays.toString(args));
//访问数组的第一个元素
System.out.println(args[0]);
System.out.println(args[1]);
System.out.println(args[2]);
System.out.println(args[3]);
} catch (Exception e) {
e.printStackTrace();
}
}
public static int test(int a,int b) throws ArithmeticException {
if(b==0) {
throw new ArithmeticException("算术异常");
}else {
return a/b;
}
}
/* 3
[hello, word, 2020]
hello
word
2020
java.lang.ArrayIndexOutOfBoundsException: 3
at com.javase18.Test.main(Test.java:20)*/
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int x = sc.nextInt(); // 等待你输入int类型,但是你输入其他不能转换成int的就抛出此异常
System.out.println(x);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 请输入一个整数: w java.util.InputMismatchException at
* java.util.Scanner.throwFor(Unknown Source) at java.util.Scanner.next(Unknown
* Source) at java.util.Scanner.nextInt(Unknown Source) at
* java.util.Scanner.nextInt(Unknown Source) at
* com.javase18.Test.main(Test.java:12)
*/
}
public class Test {
public static void main(String[] args) {
try {
int[] arr2 = new int[-5];
} catch (NegativeArraySizeException e) {
e.printStackTrace();
}
}
/*java.lang.NegativeArraySizeException
at com.javase18.Test.main(Test.java:10)*/
}
如何创建自定义异常?
①创建一个类,继承Exception或者Exception的子类
② 定义2个构造方法,一个无参,一个有String参数的构造方法
③ 分别使用super(),super(s);调用对应的父类构造器
import java.util.Scanner;
class ValueOutOf100000Exception extends RuntimeException {
private static final long serialVersionUID = 1L;
public ValueOutOf100000Exception() {
super();
}
public ValueOutOf100000Exception(String msg) {
super(msg);
}
}
public class MyExceptino {
public static void main(String[] args) {
// 输入
Scanner sc = new Scanner(System.in);
int sum = 1;
while (true) {
// 获取整数
int num = sc.nextInt();
sum *= num;
// sum>100000要捕获异常
try {
if (sum > 100000) {
throw new ValueOutOf100000Exception("乘积超过100000");
}
} catch (Exception e) {
System.out.println("sum=" + sum);
System.out.println(e.getMessage());
e.printStackTrace();
break;
}
System.out.println("sum=" + sum);
}
sc.close();
}
}
import java.util.Scanner;
class OutNmberException extends RuntimeException {
private static final long serialVersionUID = 1L;
public OutNmberException() {
super();
}
public OutNmberException(String msg) {
super(msg);
}
}
public class MyException3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数:");
int a = sc.nextInt();
if (a < 0) {
try {
throw new OutNmberException("负数没有平方根");
} catch (Exception e) {
e.printStackTrace();
}
}else {
int sum = a*a;
System.out.println(a+"的平方根为"+sum);
}
}
}