目录
1.异常
1.1 生活中的异常
场景:每天我们按照规律上下班,上下学,突然有一天你出了交通事故,导致你接下来的行程无法继续,这就是我们生活中的异常
1.2 程序中的异常
示例:
(1)这是一个非常简单的一段代码,毫无疑问可以运行,但是运行时发生意外怎么办呢,比如除数输入0,或者输入的不是数字
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
System.out.println(String.format("%d / %d = %d", num1, num2, num1/ num2));
System.out.println("感谢使用本程序!");
(2)我们用if-else去判断规避这些意外 (这里我们只对除数进行了处理),但是我们发现代码变得非常冗长,而且在其它场景我们可能无法把所有的意外都考虑到写出来,另一方面太长了,太耗费精力了
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = 0;
if (in.hasNextInt()) { // 如果输入的除数是整数
num2 = in.nextInt();
if (0 == num2) { // 如果输入的除数是0
System.err.println("输入的除数是0,程序退出。");
System.exit(1);
}
} else { // 如果输入的除数不是整数
System.err.println("输入的除数不是整数,程序退出。");
System.exit(1);
}
System.out.println(String.format("%d / %d = %d", num1, num2, num1/ num2));
System.out.println("感谢使用本程序!");
(3)前面抛砖引玉,这里引出本章节学习的异常 ,这里有小伙伴可能疑问,不是说上面的代码太长了吗,这里明显更长。但是这里只是一个简单的案例,如果到一个更复杂的场景,我们用上面的方法去诊断异常是会累死人的。下面我们将进入异常的学习
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
try {
int num2 = in.nextInt();
System.out.println(String.format("%d / %d = %d", num1, num2, num1/ num2));
}catch (InputMismatchException e1) {
System.err.println("输入的不是整数");
e1.printStackTrace();
return;
} catch (ArithmeticException e2) {
System.err.println("除数不能为0");
e2.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("00000)))))))");
}
System.out.println("感谢使用本程序!");
1.3 什么是异常
场景:正常情况下代码不会出现的场景
1.4 什么是异常处理
场景:如果代码出现与正常场景相悖的场景,需要代码去进行异常处理(当然也有代码处理不了的异常,那就叫error了)
2.try-catch
2.1 try-catch-正常
场景:如果try中的代码正常运行,则try-catch结构如同虚设,不起作用
2.2 try-catch-异常
核心要点:
如果try中的代码中同时出现多个可能出现异常的场景,只会捕获一次异常,也就是说只会执行一次catch模块分支【捕获的顺序是由上至下】
try{
//代码(存放你希望被执行的代码,这里的代码可能有异常,也可能没有异常)
}catch(异常类型 异常名称变量){
//异常处理的具体细节【捕获异常】
}
一般捕获遵循的规则是
规则1是 上小下大
规则2是 如果只捕获小的 不捕获大的(Exception)会导致异常种类捕获不完整
规则3是 如果只捕获大的 不捕获小的(具体的Exception)会导致捕获异常无法具体定位
规则4是 如果捕获的顺序不合理,比如上大下小,【由于代码的执行顺序是由上到下】,会导致只捕获大的异常,之后具体小的异常不再捕获【原因是异常只捕获一次】
2.3 try-catch-不匹配
核心要点:如果没有捕获得到对应的异常,则try catch失效
例如:上面的案例中你只捕获算数异常,当你输入不是整数发生异常时,try-catch则捕获不到,这也是为什么有上面的规则一说。
2.4 常见的异常类型
2.5 try-catch-finally-exit
核心要点:finally会在程序正常或是异常的情况都执行,做补充,但是有一个特例,就是在catch中加入System.exit(0/1)的行为,中断虚拟机,退出程序,则不执行finally语句。
2.6 try-catch-finally-return
核心要点:先执行finally,后执行return
2.7 多重catch块
引发多种类型的异常
排列catch 语句的顺序:先子类后父类(先小后大)
发生异常时按顺序逐个匹配
只执行第一个与异常类型匹配的catch语句
3.异常
3.1 声明异常【系统声明】
public class Demo01 {
//1.创建 已经声明异常的show()方法【提示这个方法中可能会有异常,也可能没有异常】
public static void show()throws Exception{
}
// public static void main(String[] args) {
//调用已经声明异常的方法【第一种调用方式】
// try{
// show();
// }catch (Exception e){
// e.printStackTrace();
// }
// }
//调用已经声明异常的方法【第二种调用方式】
public static void main(String[] args)throws Exception {
show();
}
}
3.2 抛出异常【人为抛出】
注意:throw的使用必须在已经系统声明异常的方法中使用
public class Demo02 {
private String sex = "男";
public void show()throws Exception{
if (sex.equals("男")||sex.equals("女")){
System.out.println("yes");
}else {
//人为抛出一个异常
throw new Exception("no!!!");
}
}
}
3.3 异常的分类
1.异常分两大类:Error、Exception
- 错误Error 定义:无法用代码去解决
- 异常 Exception 定义:可以用代码去捕获(解决)
2.Exception分两类:检查时异常,运行时异常
- 检查时异常(Checked Exception) 定义:代码运行前(编译时)必须处理
- 运行时异常(Runtime Exception) 定义:代码编译时不强制处理
public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//运行时异常(Runtime Exception),不加try-catch或throws也可以运行
try {
int a = scanner.nextInt();
} catch (Exception e) {
e.printStackTrace();
}
//检查时异常(Checked Exception),如果不加try-catch或throws会报错,不可运行
File file = new File("");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.Log4j
Log4j
1. 定义:开源日志记录工具
2. 功能实现以“文件”形式记录异常信息、程序正常运行关键步骤信息
3. Log4j应用
日志级别顺序:debug -> info -> warn ->error
在配置文件中定义的级别,比如定义了info则比info级别低的日志信息都不再输出
具体掌握用法
(1)在项目中加入log4j的jar包
(2)引入log4j.properties文件
(3)修改配置
(4)调试
log4j.properties文件内容示例:
第一行表示该日志记录的级别,以及解释当前文件是什么
第二段是将日志信息输出到控制台
第三段是将日志信息存储到my.log文件中
log4j.rootLogger=debug, stdout,logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=my.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%l %F %p %m%n
使用示例:
private static Logger logger= Logger.getLogger(Demo01.class.getName());
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(String.format("%d / %d = %d", num1, num2, num1
/ num2));
logger.debug(String.format("%d / %d = %d", num1, num2, num1
/ num2));
} catch (InputMismatchException e) {
logger.debug("被除数和除数必须是整数。");
} catch (ArithmeticException e) {
logger.debug("**********除数不能为零。");
} catch (Exception e) {
logger.debug("其他异常",e);
} finally {
System.out.println("感谢使用本程序!");
}
}