第一章 异常
异常:指的是程序执行中,出现非正常的情况,最终导致JVM的非正常停止。
在Java等面向对象的编程语言中,异常本身就是一个类,产生异常其实就是创建异常对象,并且抛出一个异常对象,java处理异常的方式是中断处理。
异常指的并不是语法错误,语法错误编译不会通过,不会产生字节码文件(class文件),根本不能运行 。
1.2异常体系
异常机制就是帮助我们找到程序中的问题,异常的根类是。
java.lang.Throwable,其下有两个子类:java.lang.Error与java.lang.Exception ,平时我们常说的异常是Exception。
-
Error:严重的错误,无法通过处理的错误,只能事先避免,就像绝症。
-
Exception:表示异常,异常产生后程序员可以通过代码修正,让程序继续运行,是必须要处理的。就像普通感冒等。
Throwable中常用的方法
-
public void printStackTrace():打印异常的详细信息。
-
包含了异常的类型,异常的原因,异常出现的位置,在开发和调试中都需要使用。
-
-
public String getMessage(): 获取异常发生的原因。
-
提示给用户,只提示错误原因。
-
-
public String toString(); 获取异常的类型和异常的描述信息(基本不用)。
出现异常,不要紧张,把异常的简单类名,拷贝出去搜索
1.3异常分类
异常的分类:根据编译期异还是运行期去检查异常?
-
编译期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。
-
运行期异常:runtime异常。在运行时期,检查异常,在编译时期,运行异常不会编译器检测(不报错)。
第二章 异常的处理
Java异常处理的五个关键字: try、catch、finally、throw 、thorws
2.1抛出异常throw
编写方法时,如果方法需要接受参数,那么当调用方法时传入的参数的合法性就需要判断,数据如果不合法 就该通知调用者,传递合法的参数,这时需要使用抛出异常的方式来告诉调用者。
在java中,提供throw关键字,也用来抛出一个指定的异常对象。
使用步骤:
1.创建一个异常对象。封装一些提示信息(信息可以自己编写)。
2.需要将这个这个异常对象抛出给调用者 ,throw异常对象。
throw用在方法内,用来抛出异常对象,将这个异常传递给调用者,并结束当前方法的执行。
public class Demo01 {
public static void main(String[] args) {
//创建一个数组
int[] arr = {12, 2, 3, 4, 1};
//根据索引找对应元素
int index = 444444;
int element = getElement(arr, index);
System.out.println(element);
System.out.println("over");
}
public static int getElement(int[] arr, int index) {
//判断 索引是否越界
if (index < 0 || index > arr.length - 1) {
throw new ArrayIndexOutOfBoundsException("兄弟,越界了");
}
int element = arr[index];
return element;
}
}
2.2Objects非空判断
public class Demo02 {
public static void main(String[] args) {
Demo01 demo01 =new Demo01();
demo01=null;
Demo01 demo02 = Objects.requireNonNull(demo01);
System.out.println("demo02 = " + demo02);
}
}
2.3声明异常throws
声明异常:将问题标识出来,报告给调用者,
如果方法内通过throw抛出了异常,而没有进行捕获处理,那么必须通过throws进行声明,让调用者处理。
关键字throws运用于方法声明之上,用于标识当前方法不处理异常,而是提示该方法的调用者来处理异常(抛出异常)。
异常关键字 | 概要 |
throw | 抛出异常 写在方法中 后面抛出的是一个异常对象。 |
throws | 声明异常(不代表这个类中一定会发生这种异常,一般只用在声明编译期异常) ,写在方法上 后面跟的是异常类名。 |
public class Demo03 {
public static void main(String[] args) throws FileNotFoundException,IOException {
read("aa.txt");
}
public static void read(String path) throws FileNotFoundException ,IOException {
//假设 如果传入的地址 不是a.txt 就认为该文件不存在 是一个异常
if (!path.equals("a.txt")){
throw new FileNotFoundException("文件不存在");
}
if (!path.equals("b.txt")){
throw new IOException();
}
System.out.println("11111");
}
}
2.4捕获异常try..catch
如果异常出现的话 我们必须处理异常:
在方法中使用try-catch的语句块来处理异常。
-
捕获异常: Java中对异常有针对性的语句进行捕获,可以对出现异常进行指定方式的处理。
格式:
try{
编写可能会出现异常的代码。
}catch(异常类型 e){
用来进行某种异常的捕获,实现对捕获到的异常进行处理。
// 记录日志/打印异常信息/继续抛出异常。
}
当产生异常时,必须有处理方式,要么捕获 要么声明
public class Demo04 {
public static void main(String[] args) {
try {
//当产生异常时,必须有处理方式,要么捕获 要么声明。
read("a.txt");
} catch (FileNotFoundException e) {//括号里面需要定义异常 但是具体定义什么异常呢?
// try中抛出的是什么异常 括号中就定义什么异常。
e.printStackTrace();
}catch (Exception e ){
System.out.println(e.toString());
System.out.println("22222222");
}
System.out.println("over");
}
public static void read(String path) throws FileNotFoundException, IOException {
//假设 如果传入的地址 不是a.txt 就认为该文件不存在 是一个异常
if (!path.equals("a.txt")) {
throw new FileNotFoundException("给用户看的报错信息");
}
if (!path.equals("b.txt")) {
throw new IOException();
}
System.out.println("11111");
}
}
public class Demo05 {
public static void main(String[] args) {
System.out.println(1);
System.out.println(1);
try {
System.out.println(1 / 0);
}catch (Exception e){//捕获异常了,执行该括号中的问题
e.printStackTrace();
System.out.println("我遇到了异常");
}
System.out.println(1);
System.out.println(1);
System.out.println(1);
}
}
2.5 finally 代码块
finally: 有一些特定的代码 无论异常是否发生,都需要执行。另外,异常会引发程序跳转,导致某些语句不能执行,finally主要就是为了解决这个问题,finally中的代码一定会被执行。
什么样的代码必须要最终执行?
当我们在try中打开了一些物理资源(磁盘文件/网络链接/数据库链接等),我们都需要在使用完资源,关闭打开的资源。
finally语法:
try...catch ..finally :注意: finally不能单独使用。
比如之后学习的io流中,当打开了一个关联文件的资源,最后程序不管结果如何 ,都需要关闭这个资源。
除非是 System.exit(1); 如果调用退出jvm的相关方法 ,此时finally才不会执行,否则finally永远执行。
finally代码示例:
public class Demo06 {
public static void main(String[] args) {
try{
read("aa.txt");
}catch (FileNotFoundException e){
throw new RuntimeException("这里把编译期异常,转化为运行期异常");
}finally{
System.out.println("不管发生什么 我都会执行");
}
System.out.println("over");
}
private static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")){
throw new FileNotFoundException("文件不存在");
}
}
}
2.6异常注意事项
-
运行时异常被抛出 可以不处理。即不捕获也不声明抛出。
-
如果父类抛出了多个异常,子类覆盖父类方法 ,只能抛出相同的异常。
-
父类方法没有抛出异常,子类重写父类方法时也没有抛出异常。此时子类产生异常,只能捕获处理,不能抛出。
-
当处理多个异常,捕获处理时,前面的异常类 不能是后面类的父类。
-
try catch后面追加finally时,其中代码一定会被执行,通常用于资源关闭。
-
多个异常如何处理?
-
1.多个异常分别处理。(常用)
-
2.一次捕获 多次处理。
-
3.一次捕获一次处理。(常用)
-
第三章 自定义异常
3.1 概述
为什么需要自定义异常:
很多异常没有在jdk中定义过,例如年龄负数,成绩负数,等问题。
什么是自定义异常?
在开发中根据自己实际业务定义的异常类。
例如:我们自定义一个业务逻辑异常:LoginException。一个登录异常类;
异常类如何自定义?
1.自定义一个编译期异常:自定义类 继承Exception
2.自定义一个运行期异常: 自定义类 继承RunTimeException
public class LoginException extends Exception {
public LoginException(){
}
/**
* @param message 表示异常的提示
*/
public LoginException(String message){
super(message);
System.out.println("创建了异常对象");
}
}
public class Demo09 {
// 模拟数据库中已经存在的账号
private static String[] names = {"aaa", "bbb", "ccc"};
public static void main(String[] args) {
try {
checkUserName("aaa");//可能出现异常的代码
System.out.println("注册成功");
} catch (LoginException e) {
e.printStackTrace();
}
}
//方法 判断当前账号是否存在 如果不存在 抛出异常 LoginException是编译期异常, 又想调用者处理 所以声明异常
public static boolean checkUserName(String name) throws LoginException {
for (int i = 0; i < names.length; i++) {
if (names[i].equals(name)) {
throw new LoginException("亲," + name + "已经被注册了");
}
}
return true;
}
}