异常
-
程序运行出现了不正常的情况
-
Java中提供的用于对程序出现的问题做反馈处理的机制
Throwable
-
包:java.lang
-
类定义:public class Throwable
-
Throwable 类是 Java 语言中所有错误或异常的超类
-
子类:
-
Error:严重问题,非人力可以解决,例如:栈内存溢出异常(java.lang.StackOverflowError)
-
注意:Error一般不进行处理,确保程序逻辑没有问题即可
-
JVM默认处理的方式:以红色字体打印异常详细信息
-
-
Exception:
- 编译时异常(已检查异常):除了RunTimeException其他都是编译时异常,例如ParseException
- 编译时异常在程序编译期间就会被检查出来,并提示;要求必须处理
- 运行时异常(未检查异常):RunTimeException,例如:java.lang.ArithmeticException
- 运行时异常检测不出来,所以编译期不会有提示;可以不处理,如果不处理,该异常交给JVM处理
- JVM默认处理的方式:以红色字体打印异常详细信息
- JVM默认处理的缺点:一旦程序抛出异常,则程序立即停止运行
- 编译时异常(已检查异常):除了RunTimeException其他都是编译时异常,例如ParseException
-
异常的处理机制
throws抛出异常
throws 异常类名
- 位置:异常代码所属的方法声明上,跟在方法名 参数列表后面
- 注意:
- throws将问题抛出给了方法的调用者,当真正出现异常时,JVM默认处理的方式:以红色字体打印异常详细信息
- 一旦出现异常,抛出的情况下,程序会停止执行
- 编译时异常必须处理,运行时异常可以通过throws抛出也可以不处理
- 如果程序中有多个异常可以通过
throws 异常类名1, 异常类名2, …
抛出 - 可以在
throws
后面写Exception
或者Throwable
,此时不管程序抛出什么类型的异常,父类都可以接收 - 缺点:一旦程序抛出异常,则程序立即停止运行
public class ExceptionDemo2 {
public static void main(String[] args) throws Exception {
method();
}
public static void method() throws Exception {
// DateFormat formate = new SimpleDateFormat("yyyy-MM-dd");
// ParseException 编译时异常
// 抛出异常给方法的调用者
// 一旦出现异常抛出的情况下,程序无法执行
DateFormat format = new SimpleDateFormat("yyyy/MM/dd");
Date date = format.parse("2021-11-23");
System.out.println(date);
System.out.println("hello");
// 运行时异常
int a = 5;
int b = 0;
System.out.println(a/b);
}
}
try catch
// 格式1
try {
可能出现异常的代码;
} catch(异常类 变量){
异常处理的代码
}
// 格式2
try {
可能出现异常的代码;
} catch (异常类1 变量1){
异常处理的代码;
} catch (异常类2 变量2){
异常处理的代码;
} catch (异常类3 变量3){
异常处理的代码;
}…
- 此格式可以直接写异常的父类 Exception Throwable,可以接收任意类型的异常;实际开发中,建议能细致处理的异常要详细处理。
示例:
public class ExceptionDemo4 {
public static void main(String[] args) {
// 抛出多个异常时的简化代码
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
int a = 5;
int b = 0;
try {
Date date = format.parse("2021-11-23");
System.out.println(date);
System.out.println(a/b);
} catch(Exception e){
System.out.println(e.getMessage());
}
System.out.println("end!");
}
}
// 格式3
try {
可能出现异常的代码;
} catch(异常类1|异常类2|异常类3 变量){
异常处理的代码;
}
示例:
public class ExceptionDemo4 {
public static void main(String[] args) {
// 格式 3
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
int a = 5;
int b = 0;
try {
Date date = format.parse("2021-11-23");
System.out.println(date);
System.out.println(a/b);
} catch(ParseException | ArithmeticException e){
System.out.println(e.getMessage());
}
System.out.println("end!");
}
}
- 此格式异常类必须时平级的,不能存在父子类关系
- JDK1.7开始提供的方案
- 应用场景:在实际开发中,当抛出的异常是同类型异常时才会使用该方案;
// 格式4
try {
可能出现异常的代码;
} catch(异常类 变量){
异常处理的代码;
} finally{
代码块;
}
- finally和try 语句结合使用
- finally作用:资源释放
- 特点:无论try中是否抛出异常,finally中的代码都要执行一次
- 实际开发中的应用:io流的释放,数据库相关的内容释放
示例:
public class ExceptionDemo8 {
public static void main(String[] args) {
DateFormat format = new SimpleDateFormat("yyyy/MM/dd");
Date date;
try {
date = format.parse("2021-11-23");
System.out.println(date);
} catch(ParseException e){
System.out.println(e.getMessage());
} finally {
date = null; // 释放资源
}
System.out.println("end!");
}
}
注意:
-
try中尽量只包含会出现异常的代码,其他代码越少越好,避免影响程序的运行效率
-
catch中一定要有异常处理的代码,否则一旦有异常,异常信息就会被隐藏掉
-
无论是否有异常产生,try catch之后的代码都会正常执行;如果有异常产生,则try中异常之后的代码不再执行
-
编译时异常和运行时异常都可以通过try catch来处理
-
在catch中可以嵌套try catch语句
public class ExceptionDemo5 { public static void main(String[] args) { try { System.out.println(5/0); } catch(ArithmeticException e){ System.out.println(e.getMessage()); try { System.out.println(6/0); } catch(Exception e1){ System.out.println(e1.getMessage()); } } } }
throw 和 throws
-
throw
- 用于手动抛出异常
- 一般会通过throws来继续向上抛出
public class ExceptionDemo6 { public static void main(String[] args) throws Exception{ int age = -20; if (age < 0){ // System.out.println("年龄输入错误"); // 手动抛出异常 throw new Exception(); } } }
-
位置不同
throw在方法中用于手动产生异常
throws在方法声明上,用于抛出异常,解决异常
-
作用不同
throw用于手动产生异常
throws用于抛出异常,解决异常
-
内容有区别
throw后边跟的是异常的对象
throws后边则是异常类的类名
Throwable中的方法:
-
String getMessage()
返回此 throwable 的详细消息字符串。
-
void printStackTrace()
将此 throwable 及其追踪输出至标准错误流。
-
String toString()
返回此 throwable 的简短描述。
public class ExceptionDemo6 { public static void main(String[] args) throws Exception{ try { System.out.println(5/0); } catch( ArithmeticException e){ // System.out.println(e.getMessage()); e.printStackTrace(); // 记录异常信息到日志文件中 // System.out.println(e.toString()); // 跳转到错误提示页面 } System.out.println("end!"); } }
自定义异常
-
定义一个类,此类必须继承Exception / Throwable / RuntimeException
-
提供有参构造,可以传入异常的详细描述
-
自定义异常和业务功能绑定较多,实际项目开发中使用较多
/*自定义异常*/ public class MyException extends Exception{ // 必须继承 Exception 或Throwable public MyException(){ super(); } public MyException(String message){ super(message); } } /*测试类*/ public class ExceptionDemo7 { public static void main(String[] args) throws MyException { int age = -20; if (age < 0){ throw new MyException("年龄应当大于0"); } } }
异常对方法重载和方法重写的影响
-
异常的抛出并不影响方法重载
-
方法重写:两等两小一大
-
两等:
1、方法名、参数列表一致
2、如果返回值类型是基本数据类型或void,则重写的方法必须一致
-
两小:
1、 如果返回值类型是引用类型,则子类方法返回值类型必须和父类返回值类型一致或者是子类类型
2、子类中方法抛出的异常类型必须小于等于父类方法抛出的异常类型
-
一大:
子类的访问权限修饰符必须大于父类的访问权限修饰符
public class ExceptionDemo1 { public static void main(String[] args) throws Exception{ Person p = new Student(); p.method(); } } class Person{ public void method() throws Exception{ System.out.println("Person"); } } class Student extends Person { @Override public void method() throws ParseException { DateFormat d = new SimpleDateFormat("yyyy-MM-dd"); d.parse("2021-11-25"); System.out.println("Student"); } }
-