异常抛出
1. 异常简介
import java.util.ArrayList;
public class DemoException1 {
public static void main(String[] args) {
/*TODO
异常:
需求:要买菜做饭
1.先制定计划做哪些菜 但是计划里面有问题 比如需要做红烧肉,但是菜单里面写的是排骨 -> 编译时期的异常
2.计划没问题 菜买回来了 开始做饭,明明要做红烧肉,但是用的是炖锅 -> 表示为运行时期异常
3.用铁锅做红烧肉,但是肉放多了,整个锅放了一头猪 装不下 锅太小 -> ERROR (系统性错误无法处理)
在Java中异常顶级父类为 Throwable 其子类分为三类
1.ERROR 程序运行时,发生的系统性错误
2.RuntimeException 程序运行时的一些代码 逻辑错误
3.编译异常.. 写代码时期可以避免发生
*/
// ArrayList<String> list = new ArrayList<>();
// list.add(1);
// System.out.println(1/0);
// 堆内存空间溢出
// java.lang.OutOfMemoryError: Java heap space
String guo = "";
while (true){
guo += (guo+"一头猪");
}
}
}
2. 异常种类概述
public class DemoException2 {
public static void main(String[] args) {
/*TODO
异常种类:
1.编译时期异常
① 代码语法错误 代码的位置存在问题
② 代码中的一些类型,存在不匹配
编译时期的异常,可以通过当前IDEA开发工具来展示
2.运行时期的异常
① ArithmeticException 除0错误 / by zero
② ArrayIndexOutOfBoundsException 数组访问越界
③ ConcurrentModificationException 迭代器的数据长度和数组的长度不一致导致的
④ ClassCastException 类型转换错误 一般发生在对象强制类型转换的情况下
⑤ NullPointerException 空指针异常 对对象进行调用时,其内存地址指向为空
注意:特点属于 RuntimeException 下的一个子类
在运行时会报错,报错后整个程序停止运行
如果当程序出现问题,需要对当前的错误进行捕获处理
比如对于 NullPointerException 异常,如果出现,那么可以对其进行重新创建对象
继续通过对象的方法进行调用
*/
// System.out.println(1/0);
// int[] ints = new int[3];
// System.out.println(ints[3]);
Exp exp = null;
// exp.printInfo();
// TODO 如果当exp的变量,指向的是为null,那么可以调用其 new 方法重新创建一个对象,赋予给变量
if (exp == null) {
exp = new Exp();
}
exp.printInfo();
// TODO 上述的方式属于,问题错误没有发生,但是可以提前进行预防
// 对于已经发生的错误,如果要进行处理就需要使用 try .. catch 方式进行捕获
}
// new Student();
}
class Exp {
public void printInfo() {
System.out.println("这是Exp类中的printInfo方法...");
}
}
3. Try/Catch
public class DemoTryCatch {
public static void main(String[] args) {
/*
TODO 异常捕获
try
...
catch (异常的类型 变量名)=> 抓,捕获
...
Java是一个面向对象的语言,所有的异常类 NullPointerException 也是会有一个对象
于是需要使用变量调用对象
*/
/*
TODO
int[] ints = new int[3];
System.out.println(ints[3]);
对于代码如果发生错误,那么错误的内容包含有三个方面:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at com.shujia.day11.Demo05TryCatch.main(Demo05TryCatch.java:17)
异常类型:
ArrayIndexOutOfBoundsException
异常提示信息:
3
错误发生位置:
at com.shujia.day11.Demo05TryCatch.main(Demo05TryCatch.java:17)
对于排除问题的思路:
① 获取完整的日志信息 错误的位置不一定就发生在代码指定的位置
② 找到错误的类型 根据类型可以确定当前问题发生的范围,
同时也可以根据类型将错误捕获,让程序继续运行
③ 根据错误的提示信息,寻找线索 提示信息中一般都会打印一些数据
④ 根据代码指定的位置,对其进行debug,重新运行,查看每个变量中的数据是否符合要求
⑤ 如果因为自身对程序的了解不够,导致程序问题寻找不到,那么尝试换种方式
*/
Exp exp = getExp();
try {
exp.printInfo();
// 也可以使用它们的父类Exception
}catch (NullPointerException exception){
// 如果发生错误了,就可以捕获到错误的对象 对该对象调用其方法
// System.out.println("错误提示信息:"+ exception.getMessage());
System.err.println("错误提示信息:"+ exception.getMessage());
// 打印整个的错误提示信息
exception.printStackTrace();
// 如何将日志信息写入到文件中进行保存?
}
// TODO 当程序被捕获时,那么可以继续运行代码
System.out.println("程序执行到这里了....");
// TODO 对于多行代码中可能会出现有多个错误,但是也不确定
try {
System.out.println(3/0);
int[] ints = new int[2];
System.out.println(ints[2]);
// 对于错误类型有两种 ArrayIndexOutOfBoundsException 或者 ArithmeticException
}catch (ArrayIndexOutOfBoundsException | ArithmeticException exception){
System.out.println("发生错误了...");
System.err.println(exception.getMessage());
exception.printStackTrace();
}
/*
TODO 对于多种错误类型,可以直接使用父类 Exception 表示
由于异常也是一个具体的类,也符合对象的多态特性
于是子类异常对象可以指向父类 Exception变量 在调用时,
比如 printStackTrace 方法是调用其具体对象的
*/
try {
System.out.println(3/0);
int[] ints = new int[2];
System.out.println(ints[2]);
}catch (Exception exception){
// exception.getMessage();
System.out.println("捕获到了一个异常,但是暂时不知道是什么");
exception.printStackTrace();
}
/*
给定的异常太过于具体没有捕获到
TODO 需求:当不管代码是否执行正常,都要执行某些代码..
比如:如果对Mysql数据库进行操作,操作过程中代码出错了
但是Mysql的连接需要进行关闭,否则对于Mysql数据库来说,有一个连接被占用了
final格式:
try{
可能发生错误的代码
}catch(){
当指定的错误类型,被获取到后的操作
}finally{
不管代码是否有错误,都会执行..
}
*/
try {
String s = null;
s.split("");
System.out.println(3/0);
int[] ints = new int[2];
System.out.println(ints[2]);
}catch (ArrayIndexOutOfBoundsException | ArithmeticException exception){
System.out.println("捕获到了一个异常,但是暂时不知道是什么");
exception.printStackTrace();
}finally {
System.out.println("不管程序是否有错误,该代码块中得代码都会被执行...");
}
System.out.println("该行被打印表示程序正常执行完成...");
}
// 假设这是另外一个Jar包或者其他程序员开发的代码 不能进行改变
public static Exp getExp() {
return null;
}
}
4. 自定义异常
public class DemoMyException {
// TODO 对于main方法 也可以进行异常抛出,但是一旦遇到异常,程序终止
public static void main(String[] args) throws MyDefineException {
/*
TODO 如果想要定义一个自定义的错误类型
throw:通过该关键字可以 抛出一个异常的对象,让其产生错误
*/
try {
/*
com.shujia.day11.MyDefineException: 这是自定义的异常
at com.shujia.day11.Demo06MyException.main(Demo06MyException.java:11)
*/
throw new MyDefineException("这是自定义的异常");
} catch (MyDefineException exception) {
System.out.println(exception.getMessage());
exception.printStackTrace();
}
/*
TODO 当在fun函数中定义了一个错误的发生位置,那么对于main方法中,并没有提示其错误
那么如何让main方法知道fun函数中可能会发生错误?
可以使用throws对异常进行抛出,意思表达为当程序中出现问题,自己不处理交给调用方进行处理
由于在main方法中进行调用,那么就需要在main中进行处理
*/
// System.out.println(3/0);
// try {
// fun(3, 0); // 经过捕获之后就没有异常了
// }catch (MyDefineException exception){
// exception.printStackTrace();
// }
fun(2, 0);
System.out.println("程序是否能打印改行?");
}
// public static void fun(int a, int b) {
// TODO 方法内不处理,交给调用方进行处理
public static void fun(int a, int b) throws MyDefineException,NullPointerException {
if (b == 0) {
// 直接处理由于有 throw 执行到该处时肯定会发生错误,程序退出...
throw new MyDefineException("除数不能为零,抛出异常,请检查逻辑");
} else {
System.out.println(a / b);
}
// TODO 方法内自行处理
// if (b == 0) {
// try {
// throw new MyDefineException("除数不能为零,抛出异常,请检查逻辑");
// } catch (MyDefineException exception) {
// exception.printStackTrace();
// }
// } else {
// System.out.println(a / b);
// }
}
}
class MyDefineException extends Exception {
// 如果当遇到自定义的类型时,想要去打印自定义的信息怎么做
// 打印信息 可以使用 getMessage()
public MyDefineException(String message) {
super(message);
}
}
5. 异常总结
public class DemoExceptionTxt {
public static void main(String[] args) {
/*TODO
异常操作的总结:
1.对于可能会发生错误的代码处理方式
① 使用 try catch 进行捕获异常 程序不会终止
如果有必须要执行的代码,可以放到 finally 代码块中
② 使用 throws 对可能发生的异常进行抛出,交给调用方进行处理
如果调用方也不处理,那么遇到错误,程序会终止
2.如果想定义错误
1.构建一个自定义异常类继承于 Exception 或者其子类
2. 通过 throw 方法触发 其异常类的对象
finally的作用
用于释放资源,在IO流操作和数据库操作中会见到: 比如对Mysql连接进行关闭操作
TODO throws和throw的区别:
throws
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常
异常可以用埋雷、排雷的方式理解
*/
/*
如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
finally代码是必须要执行的,是在return之前,函数执行完成之前执行
*/
System.out.println(fun());
}
public static int fun(){
try {
System.out.println("return之前...");
return 0;
// System.out.println("return之后...");
}catch (Exception exception){
System.out.println("异常被捕获...");
}finally {
System.out.println("finally代码被执行...");
}
return 1;
}
}