文章目录
Day19 Java基础-异常
主要内容
- 异常
- try-catch-finally
- 异常分类
- throws和throw
- 自定义异常
- 面向对象案例:猜丁壳(石头剪子布)
引入异常
注意:异常处理完之后要继续执行后面的代码
面对异常该怎么办?
- 方法1:由开发者通过if-else来解决异常问题
缺点:代码臃肿,业务代码和异常处理代码放一起
程序员要花很大精力“堵漏洞”
程序员很难堵住所有“漏洞”,对程序员本身要求较高
- 方法2:开发者不需要通过if-else来解决异常问题,而是Java提供异常处理机制。它将异常处理代码和业务代码分离,使程序更优雅、更好的容错性、高健壮性
程序中预先想好了对付异常的处理办法-------->程序运行------>异常!-------->产生异常对象---------->捕获异常--------->处理异常--------->处理完毕,程序继续运行
异常(Exception)就是在程序的运行过程中所发生的不正常的事件,他会中断正在运行的程序(所需文件找不到、网络连接不通或中断、算术运算错、被0除,数组下标越界、装载一个不存在的类或者对null对象操作、类型转换异常…)
当Java程序出现以上的异常时,就会在所处的方法中产生一个异常对象。这个异常对象包括异常的类型,异常出现时程序的运行状态以及对异常的详细描述
Java的异常处理是通过5个关键字来实现的:try catch finally throw throws
捕获异常 | |
---|---|
try-------------> | 执行可能产生异常的代码 |
catch---------> | 捕获异常 |
finally----------> | 无论是否发生异常,代码总能执行 |
声明异常 | |
---|---|
throws-------------> | 声明方法可能要抛出的各种异常 |
抛出异常 | |
---|---|
throw------------> | 手动抛出异常 |
优点:Java已经提供了异常处理机制,发生异常后,会给出异常类型、异常提示信息、异常的位置
缺点:出现异常后,后续语句不执行了;提示信息太专业,可读性差
解决:try-catch-finally 处理异常;throws 抛出异常不处理,调用者处理
public class excep {
public static void main(String[] args) {
//try里面的是可能会出错的代码
try {
//1.输入总分
Scanner input = new Scanner(System.in);
System.out.println("请输入总分");
int num1 = input.nextInt();
//2.输入人数
System.out.println("请输入人数");
int num2 = input.nextInt();
//3.计算平均分并输出
int result = num1 / num2;
System.out.println("平均分是:"+result);
}catch (Exception e){
System.err.println(e.toString());
}
System.out.println("3q3q");
System.out.println("bye");
}
}
try-catch的执行情况
-
情况1:try块中代码没有出现异常
不执行catch代码块,执行catch块后面的代码
-
情况2:try块中代码出现异常,catch中异常类型匹配(相同或者父类)
执行catch块代码,执行catch块后边的代码
-
情况3:try块中代码出现异常,catch中异常类型不匹配
不执行catch块代码,不执行catch块后边的代码,程序会中断运行
注意:
- 出现异常后,Java会生成相应的异常对象,Java系统寻找匹配的catch块,找到后将异常对象付给catch块异常参数
- 出现异常后,try块中尚未执行的语句不会执行
- 出现异常后并处理后,catch块后面的语句还会执行
public class excep {
public static void main(String[] args) {
//try里面的是可能会出错的代码
try {
//1.输入总分
Scanner input = new Scanner(System.in);
System.out.println("请输入总分");
int num1 = input.nextInt();
//2.输入人数
System.out.println("请输入人数");
int num2 = input.nextInt();
//3.计算平均分并输出
int result = num1 / num2;
System.out.println("平均分是:"+result);
}catch (Exception e){ //Exception e = new InputMismatchException(); 多态
/*情况1:输出自定义信息
System.out.println("你输入的数字有误");
*/
/*情况2:输出系统信息
e.printStackTrace();
*/
/*
* 情况3:只输出提示信息
* System.out.println(e.getMessage());
*/
/*
* System.err.println(e.toString());
* */
/*
* 情况4:向上继续抛(抛不抛到后面讲)(分层开发,底层向上抛)
*/
throw e;
}
System.out.println("3q3q");
System.out.println("bye");
}
}
异常类型 | 说明 |
---|---|
Exception | 异常层次结构的根类 |
ArithmeticException | 算术错误情形,如以零作除数 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
NullPointerException | 尝试访问null对象成员 |
ClassNotFoundException | 不能接在所需的类 |
InputMismatchException | 欲得到数据类型与实际输入类型不匹配 |
IllegalArgumentException | 方法接收到非法参数 |
ClassCastException | 对象强制类型转换出错 |
NumberFormatException | 数字格式转换异常,如把“ac”转换成数字 |
问题1:哪些情况下的catch后面的语句不执行
情况1:throw e;
情况2:catch的异常类型不匹配
情况3:遇到了return语句
问题2:不管成功失败,某些语句必须执行
加finally语句
问题3:finally语句的作用,哪些语句应该放到finally中
conn.close();数据库、fis.close() fos.close() IO流
socket.close()
问题4:执行的顺序
System.out.println(“平均分是:”+result);
System.out.println(“3q3q”);
return;
问题5:有没有例外的情况?
System.exit(0); 退出虚拟机
return:结束当前方法
多重catch处理异常
import javax.naming.AuthenticationException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class excep {
public static void main(String[] args) {
//try里面的是可能会出错的代码
try {
//1.输入总分
Scanner input = new Scanner(System.in);
System.out.println("请输入总分");
int num1 = input.nextInt();
//2.输入人数
System.out.println("请输入人数");
int num2 = input.nextInt();
//3.计算平均分并输出
int result = num1 / num2;
System.out.println("平均分是:"+result);
return;
}catch (ArithmeticException e){
System.out.println("除数不能为0");
}
catch (InputMismatchException e){
System.out.println("必须为数字");
}
catch (Exception e){
System.out.println("其他异常");
}
finally {
System.out.println("3q3q");
}
System.out.println("bye");
}
}
-
当引发异常时,会按照顺序来查看每个catch语句,并执行第一个与异常匹配的catch语句
-
执行其中一条catch语句后,其后catch语句将被忽略
-
在安排catch语句的顺序时,首先应该捕获最特殊的异常,然后再逐渐一般化,即先子类后父类
-
了解JDK7的异常处理方式
catch(ArithmeticException | InputMismatchException e){}
异常体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6MjikOQe-1634321276350)(C:\Users\50092\Desktop\JAVA\截图\000000001.jpeg)]
Error
- Error类层次描述了Java运行时系统内部错误和资源耗尽错误,一般指与JVM或动态加载等相关问题,如虚拟机错误,动态链接失败,系统崩溃等。
- 这类错误我们无法控制的,同时也是非常罕见的错误。所以在编程中,不去处理这类错误。我们不需要管理Error
Exception
- 所有异常类的父类,其子类对应了各种各样可能出现的异常事件
Exception分类
-
运行时异常 Runtime Exception(unchecked Exception)
可不必对其处理,系统自动检测处理
一类特殊的异常,如被0除、数组下标超范围等,其产生比较频繁,处理麻烦,如果显式的声明或捕获将会对程序可读性和运行效率影响很大
-
检查异常 Checked Exception
必须捕获进行处理,否则会出现编译错误
注意:只有Java提供了Checked异常,体现了Java的严谨性,提高了Java的健壮性。同时也是一个备受争议的问题
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Locale;
public class exp2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//int[] arr = new int[10];
//System.out.println(arr[11]); //ArrayIndexOutOfBoundsException:数组下标越界
System.out.println("=========");
//String str = "sad";
//str = null;
// System.out.println(str.toUpperCase()); //NullPointerException 空指针
System.out.println(10/0); //ArithmeticException:算术异常
//以上都属于运行时异常
//检查异常 checked exception
try {
Class.forName("java.lang.String").newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Class.forName("java.lang.String").newInstance(); //继续向上抛,让调用者处理
try {
new FileOutputStream("c:/abc.txt");//IO流 处理两种方法
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
异常处理:throws,throw
手动抛出异常throw
- Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要手动创建并抛出
- 在捕获一个异常前,必须有一段代码先生成异常对象并把它抛出。这个过程我们可以手动做,也可以由JRE来实现,但是他们调用的都是throw子句
- 注意抛出运行时异常和Checked异常的区别
抛出Checked异常,该throw语句要目处于try块中,要么方法签名中使用throws抛出
- 抛出运行时异常,没有以上要求
声明异常throws
- 当Checked Exception产生时,不一定立刻处理它,可以再把异常Throws出去
- 如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开
- 子类声明的异常范围不能超过父类声明范围:父类没有声明异常,子类也不能;不可抛出原有方法抛出异常类的父类或上层类
import java.util.Scanner;
/*
* throws和throw的区别:
* 1.作用:
* throws声明,说明方法里面有异常
* throw产生异常的地方,并往上抛
*
* 2.位置
* throws在方法签名里面
* throw在方法体里面
*
* 3.数量
* throws后面跟的是一个一个类
* throw 是new一个对象,也只能一个
* */
public class clacavg {
public static void main(String[] args) {
try {
clacavg();
} catch (Exception e) {
e.printStackTrace();
}
//第二种办法:clacavg(); 向上抛throws Exception
}
public static void clacavg() throws Exception {
//1.输入总分
Scanner input = new Scanner(System.in);
System.out.println("请输入总分:");
int num1 = input.nextInt();
//2.输入人数
System.out.println("输入人数:");
int num2 = input.nextInt();
//如果人数是负数,产生一个异常并抛出
if(num2<0){
//throw new RuntimeException("输入人数不能小于0"); 抛出的运行异常不需要抛出
throw new Exception("输入人数不能小于0"+ num2);//自己检查异常必须抛出
}
//3.计算平均数并输出
int result = num1 / num2;
System.out.println("平均分是:"+ result);
System.out.println("3q3q");
System.out.println("886");
}
}
public class Person {
private String name;
private int age;
//无参构造方法
public Person() {
}
//有参构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws Exception {
if(age<0 || age>130){
//System.out.println("年龄输入错误");
//return;
//throw new RuntimeException("年龄输入错误");//遇到throw程序会自动结束,比如这句完了就没了
throw new Exception("年龄输入错误");
}
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args){
Person person = new Person();
try {
person.setAge(221);
} catch (Exception e) {
e.printStackTrace();
}//用了try-catch,后面的代码继续执行,向上抛throws后面的代码不执行
person.setName("张三");
System.out.println(person.toString());
}
}
自定义异常
//自定义异常:人数不是负数的异常
//继承 分为运行时异常(RuntimeException)和异常(Exception)
public class CountMinusException extends Exception{
public CountMinusException() {
super();
}
public CountMinusException(String message) {
super(message);
}
}
异常链
实战再讲
rintStackTrace();
}//用了try-catch,后面的代码继续执行,向上抛throws后面的代码不执行
person.setName(“张三”);
System.out.println(person.toString());
}
}
## 自定义异常
```java
//自定义异常:人数不是负数的异常
//继承 分为运行时异常(RuntimeException)和异常(Exception)
public class CountMinusException extends Exception{
public CountMinusException() {
super();
}
public CountMinusException(String message) {
super(message);
}
}
异常链
实战再讲