JavaLearn # 异常
Posted LRcoding
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaLearn # 异常相关的知识,希望对你有一定的参考价值。
1. 异常
异常,总会发生的情况,异常处理完,代码要继续执行
例如:除数为 0 ,或者不为数字。
面对异常该怎么办呢?
- 由开发者通过 if-else 来解决 ==》 代码臃肿,对程序员要求较高
- Java本身的异常处理机制,我们只需要捕捉,处理异常即可,处理完程序继续执行
异常处理过程:
- 捕获异常:
try
:内含可能产生异常的代码catch
:捕获异常finally
:无论是否发生异常,程序都需要执行的代码
- 声明异常(有异常,自己不处理):
throws
:声明方法可能要抛出的各种异常
- 抛出异常(异常产生的地方):
throw
:手动抛出异常
示例:输入班级总分,输入人数,计算平均分
public class TestException {
public static void main(String[] args) {
// 1. 输入总分
Scanner sc = new Scanner(System.in);
System.out.print("输入总分: ");
int score = sc.nextInt(); // 可能输入的不是 int 类型,报异常
// 2. 输入人数
System.out.print("输入班级人数: ");
int num = sc.nextInt();
// 3. 计算平均分并输出
int res = score / num; // 此处除法,容易出现异常
System.out.println("平均分:" + res);
System.out.println("ending.....");
}
}
解决:try-catch-finally 处理异常; throws 抛出异常不处理,调用者处理
// 将可能出现异常的语句,放到 try 语句里,catch 处理异常,finally 总会执行的代码
try {
int score = sc.nextInt();
int num = sc.nextInt();
int res = score / num;
} catch (Exception e) {
System.out.println("异常出现了");
} finally {
System.out.println("总会执行的代码");
}
// 处理完异常后,后续的代码可以继续执行
System.out.println("可以继续执行 ");
try-catch执行情况:
- 情况1:try 代码块中没有异常 ==》 不执行 catch 代码块,执行后续代码
- 情况2:try 代码块中出现异常,catch 中异常类型匹配(相同或者父类) ==》 执行 catch 代码块,执行后续代码
- 情况3:try 代码块中出现异常,catch 中异常类型不匹配 ==》 不执行 catch 代码块,不执行后续代码
注意:
- 出现异常后,Java会产生相应的异常对象,Java系统寻找匹配的 catch 块,找到后将异常对象赋给catch块异常参数
- 出现异常后,try 块中尚未执行的代码语句,不会执行
- 出现异常并处理后,catch 块后面的语句还会执行
catch 块中如何处理异常:
- 输出用户自定义的异常信息:
System.err.println("除数不能为 0");
- 调用异常对象的方法输出异常信息:
e.printStackTrace();
异常的堆栈信息 - 继续向上抛出异常:
throw e
catch 后续的代码块不执行
加上 finally 后的执行顺序:
- 无论 try 中是否发生异常,finally 中的代码都要被执行,所以如果在 try 语句中有 return 方法,那么顺序为正常执行 return 之前的,然后执行 finally 中代码,然后执行 return
- 但是如果使用了
System.exit(0);
那么程序只执行到这个语句处
多重 catch 处理异常:只匹配一个异常
try{
int score = sc.nextInt();
int res = score / num; // 此处除法,容易出现异常
} catch (ArithmeticException e) {
System.err.println("除数不能为 0");
} catch (InputMismatchException e) {
System.err.println("必须输入数字");
} catch (Exception e) {
e.printStackTrace();
}
2. 异常体系
Error:
- Java 运行时系统内部错误或资源耗尽错误,一般指与 JVM 或动态加载等相关的问题
- 这类错误是我们无法控制的,同时也非常罕见,不需要去管理 Error
Exception:
- 所有异常的父类,其子类对应了各种各样可能出现的异常
Exception分类:
-
Runtime Exception 运行时异常
可不必对其处理,系统自动检测处理,其产生比较繁琐,处理麻烦(被0整除,数组越界,空指针等)
-
Checked Exception 检查异常
必须捕获处理,否则会编译错误,只有Java提供了检查异常
Class.forName("java.lang.String").newInstance(); 两种处理方式: // 1. 用 try-catch 包围 // 2. 用 throws 继续向上抛,让调用者进行异常处理
3. throw 和 throws
- 作用:
- throws 是声明一下,方法里面有异常,调用者要进行处理
- throw 声明的是产生异常的地方,要往上抛,让调用者知道
- 位置:
- throws 写在方法的签名位置(声明的地方)
- throw 写在方法体内部
- 数量:
- throws 后面可以加
多个
类 - throw 后面只能由
一个
对象
- throws 后面可以加
需求1:如果班级人数输入的为负数,抛出异常
-
抛出运行时异常
throw new RuntimeException
System.out.print("输入班级人数: "); int num = sc.nextInt(); if (num < 0) { // =========== throw 是产生异常的地方,进行抛出 ================ throw new RuntimeException("人数不能是负数"); }
-
抛出检查异常
throw new Exception
// =========== throws 抛出异常,告知调用者,要进行异常处理 ================ public void getAvg() throws Exception { System.out.print("输入班级人数: "); int num = sc.nextInt(); if (num < 0) { throw new Exception("人数不能是负数"); } }
需求2:限制一下年龄的范围
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) {
// 第1种:抛出运行时异常,可以不进行处理
//throw new RuntimeException("年龄范围错误(0-130)");
// 第2种:抛出检查异常,调用的地方必须处理,声明方法时,必须加上 throws
throw new Exception("年龄范围错误(0-130)");
}
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
Person p = new Person();
p.setName("张三");
try {
p.setAge(150);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(p.toString());
}
}
4. 自定义异常
上边代码运行后,会产生异常,但是不友好,不能见名知意
解决:我们可以自定义异常类型,抛出时,抛出我们自定义的异常
自定义异常类AgeException:
// 检查异常:继承 Exception, 运行时异常:继承 RuntimeException
public class AgeException extends Exception {
public AgeException () {
}
public AgeException (String message) {
super(message);
}
}
使用自定义异常:
public class Person {
private int age;
public void setAge(int age) throws AgeException { //============== 抛出自定义异常类 ===========
if (age < 0 || age > 130) {
throw new AgeException("年龄范围错误(0-130)");
}
this.age = age;
}
public static void main(String[] args) {
Person p = new Person();
try {
p.setAge(150);
} catch (AgeException e) { //============== 使用自定义异常类进行捕获 ===========
e.printStackTrace();
}
System.out.println(p.toString());
}
}
扩展:异常链,项目分层之后,底层出现问题,向上抛出,到合适的位置进行捕获处理
以上是关于JavaLearn # 异常的主要内容,如果未能解决你的问题,请参考以下文章
JavaLearn# (13)多线程:线程生命周期线程控制线程同步线程通信线程池ForkJoin框架
mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段
mvn命令异常:An error has occurred in Javadoc report generation: Unable to find javadoc command异常已解决(代码片段
springcloud报错-------关于 hystrix 的异常 FallbackDefinitionException:fallback method wasn't found(代码片段