异常
1.异常体系结构介绍
Throwable
Error(错误,仅靠程序本身无法恢复的错误) Exception(异常,因为代码导致的各种不正常情况)
Exception分为
运行时异常(RuntimeException):RuntimeException及其子类都属于运行时异常
检查(受检)异常(CheckedException):除了运行时异常以外的其他异常属于检查异常
2.try-catch处理异常
try : try代码块中用于执行可能出现异常的代码
catch : catch结构用于捕获可能出现的异常
try 不能单独出现 必须结合catch 或者 catch-finally 或者 finally
catch 也不能单独出现
捕获的异常和出现异常 类型匹配则能顺利捕获到 如果类型不匹配 则程序依然中断
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 10:13
* try : try代码块中用于执行可能出现异常的代码
* catch : catch结构用于捕获可能出现的异常
*
* try 不能单独出现 必须结合catch 或者 catch-finally 或者 finally
* catch 也不能单独出现
*
* 捕获的异常和出现异常 类型匹配则能顺利捕获到 如果类型不匹配 则程序依然中断
*
*/
public class TestTryCatch1 {
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
}catch(InputMismatchException e){
System.err.println("出现了异常");
e.printStackTrace(); // 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
}
System.out.println("感谢使用本程序!");
}
}
使用try-catch结构捕获多个异常
如果在try结构中可能出现多种异常 我们可以使用多个catch块来捕获不同的异常
多个catch书写注意顺序,先子类 后父类 否则编译报错
不推荐直接使用异常父类 Exception捕获所有异常的这种写法 因为代码阅读性差
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 10:27
* 使用try-catch结构捕获多个异常
*
* 如果在try结构中可能出现多种异常 我们可以使用多个catch块来捕获不同的异常
* 多个catch书写注意顺序,先子类 后父类 否则编译报错
* 不推荐直接使用异常父类 Exception捕获所有异常的这种写法 因为代码阅读性差
*/
public class TestTryCatch2 {
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
}catch(InputMismatchException e){ // JDK1.5 支持使用或 分割两个异常类型 | ArithmeticException
System.err.println("出现了输入不匹配异常");
e.printStackTrace(); // 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
}catch(ArithmeticException e){
System.err.println("出现了算数运算异常");
e.printStackTrace();// 调用继承自Throwable类中的 printStackTrace() 打印异常堆栈信息
}catch(Exception e){
System.err.println("出现了其他异常");
e.printStackTrace();
}
System.out.println("感谢使用本程序!");
}
}
3.finally处理异常
finally关键字:finally代码块 表示用于处理任何情况下都需要执行的代码
不管是否出现异常 以及 异常是否被捕获到
finally不能单独出现 必须结合 try-catch 或者 try结构
finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 10:38
* finally关键字:finally代码块 表示用于处理任何情况下都需要执行的代码
* 不管是否出现异常 以及 异常是否被捕获到
*
* finally不能单独出现 必须结合 try-catch 或者 try结构
*
* finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
*
*/
public class TestFinally1 {
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
}catch(InputMismatchException e){
e.printStackTrace();
}finally{
System.out.println("感谢使用本程序!");
}
}
}
finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
System.exit(int status) :System类中提供的静态方法 作用为退出JVM虚拟机
参数为int类型 传入任何数值作用相同
含义不同 : 0表示正常退出 非0表示非正常退出
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 10:41
* finally不执行的唯一情况:在执行finally之前 退出JVM虚拟机
*
* System.exit(int status) :System类中提供的静态方法 作用为退出JVM虚拟机
* 参数为int类型 传入任何数值作用相同
* 含义不同 : 0表示正常退出 非0表示非正常退出
*/
public class TestFinally2 {
public static void main(String[] args) {
try{
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(num1 + "/" + num2 + "=" + num1 / num2);
System.exit(0);
}catch(InputMismatchException e){
e.printStackTrace();
}finally{
System.out.println("感谢使用本程序!");
}
}
}
finally面试题:
1.try中存在return finally中的代码是否还执行
执行
2.try中书写了return语句 返回了结果 finally中对返回值的操作是否还会影响返回值
如果是基本数据类型 不影响
如果是引用数据类型 影响
import java.util.Arrays;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 10:47
* finally面试题:
* 1.try中存在return finally中的代码是否还执行
* 执行
* 2.try中书写了return语句 返回了结果 finally中对返回值的操作是否还会影响返回值
* 如果是基本数据类型 不影响
* 如果是引用数据类型 影响
*/
public class TestFinally3 {
public static int m1(){
int num = 10;
try {
num++;
return num;
}catch(Exception e){
e.printStackTrace();
}finally{
num++;
}
return num;
}
public static int[] m2(){
int [] nums = {1,2,3,4,5};
try{
return nums;
}catch(Exception e){
e.printStackTrace();
}finally{
for (int i = 0; i < nums.length; i++) {
nums[i]++;
}
}
return nums;
}
public static void main(String[] args) {
System.out.println(m1());
System.out.println(Arrays.toString(m2()));
}
}
4. throw和throws
throw : 用于抛出异常 书写在方法体内 作为一条单独的语句书写 一句只能抛出一个异常
需要根据抛出的异常不同,决定是否要声明
如果抛出的为运行时异常,则不必声明
如果抛出的为检查异常,则必须声明
throws : 用于声明异常 书写在方法声明形参列表之后 可以声明多个异常 多个异常之间使用逗号分割
调用者需要根据声明的异常类型不同,做出不同的处理
运行时异常,调用者无需处理
检查异常,调用者必须处理
1.使用try-catch处理
2.继续声明给JVM虚拟机(不处理)
import java.io.IOException;
import java.sql.SQLException;
/**
* @author WHD
* @description TODO
* @date 2024/1/15 14:11
* throw : 用于抛出异常 书写在方法体内 作为一条单独的语句书写 一句只能抛出一个异常
* 需要根据抛出的异常不同,决定是否要声明
* 如果抛出的为运行时异常,则不必声明
* 如果抛出的为检查异常,则必须声明
*
* throws : 用于声明异常 书写在方法声明形参列表之后 可以声明多个异常 多个异常之间使用逗号分割
*
* 调用者需要根据声明的异常类型不同,做出不同的处理
* 运行时异常,调用者无需处理
* 检查异常,调用者必须处理
* 1.使用try-catch处理
* 2.继续声明给JVM虚拟机(不处理)
*
*/
public class TestThrowThrows {
public static void m1() throws ArithmeticException{
System.out.println(10 / 0);
}
public static void m2() throws ClassNotFoundException{}
public static void m3() throws SQLException {}
public static void m4() throws RuntimeException{}
public static void m5(){
throw new RuntimeException("运行时异常");
}
public static void m6() throws IOException {
throw new IOException();
}
public static void main(String[] args) throws SQLException {
try {
m6();
} catch (IOException e) {
e.printStackTrace();
}
m5();
m1();
try {
m2();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
m3();
m4();
}
}
/**
* @author WHD
* @description TODO
* @date 2024/1/15 14:23
* 人类
* 属性:名字 年龄
*/
public class Person {
private String name;
private int age;
private char sex;
public char getSex() {
return sex;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 0 && age <= 130){
this.age = age;
}else{
throw new RuntimeException("年龄不合法:"+ age +",有效范围为:1 ~ 130" );
}
}
public void setSex(char sex) throws Exception {
if(sex == '男' || sex == '女'){
this.sex = sex;
}else{
throw new Exception("性别不合法:" + sex);
}
}
public String getName() {
return name;
}
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("赵四");
p1.setAge(100);
try {
p1.setSex('中');
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序结束");
}
}
5.自定义异常
自定义异常:当JDK提供的异常不能满足开发需求,我们需要自定义异常
1.继承异常父类 Throwable Exception RuntimeException 三者任意其中一个
2.编写有参构造方法初始化异常信息
/**
* @author WHD
* @description TODO
* @date 2024/1/15 14:23
* 人类
* 属性:名字 年龄
*/
public class Person {
private String name;
private int age;
private char sex;
public char getSex() {
return sex;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws InputAgeOutOfBoundsException {
if(age > 0 && age <= 130){
this.age = age;
}else{
throw new InputAgeOutOfBoundsException("年龄不合法:"+ age +",有效范围为:1 ~ 130" );
}
}
public void setSex(char sex) {
if(sex == '男' || sex == '女'){
this.sex = sex;
}else{
throw new InputSexException("性别不合法:" + sex);
}
}
public String getName() {
return name;
}
public static void main(String[] args) throws InputAgeOutOfBoundsException {
Person p1 = new Person();
p1.setName("赵四");
p1.setAge(110);
p1.setSex('6');
System.out.println("程序结束");
}
}
/**
* @author WHD
* @description TODO
* @date 2024/1/15 14:38
* 自定义异常:当JDK提供的异常不能满足开发需求,我们需要自定义异常
* 1.继承异常父类 Throwable Exception RuntimeException 三者任意其中一个
* 2.编写有参构造方法初始化异常信息
*
*/
public class InputAgeOutOfBoundsException extends Throwable{
public InputAgeOutOfBoundsException(String message){
super(message);
}
}
/**
* @author WHD
* @description TODO
* @date 2024/1/15 14:44
*/
public class InputSexException extends RuntimeException{
public InputSexException(String message){
super(message);
}
}