1.程序中的异常
public class TestException {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入被除数:");
int num1 = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println(String.format("%d / %d = %d", num1, num2, num1 / num2));
//java.lang.ArithmeticException
//java.util.InputMismatchException
}
}
-
输入正常,程序正常执行完成
-
当除数输入0:java.lang.ArithmeticException,计算异常
-
当除数输入a:java.util.InputMismatchException,输入不匹配异常
-
在程序的运行过程中,可能会出现一些问题,最终导致jvm非正常停止,我们称之为运行时异常
2.异常的处理
-
通过自己写if-else代码判断异常情况
-
代码臃肿
-
会花费很多的精力考虑异常情况
-
很难考虑到所有的异常
-
-
通过Java的异常处理机制,也就是由java系统来堵漏洞
-
在java等面向对象的编程语言中,异常本身就是一个类,产生异常就是创建异常对象并抛出一个异常对象
-
java异常处理的五个关键字
-
try、catch、finally、throws、throw
-
-
3.异常的分类
-
java.lang.Throwable:是所有异常和错误的超类
-
Exception:所有异常的基类
-
编译时异常:ClassNotFoundException、IOException、SQLException,写代码时必须处理
-
运行时异常:RuntimeException,
-
如数组下标越界异常ArrayIndexOutOfBoundsException,
-
空指针异常 NullPointerException
-
程序运行过程中出现的异常
-
-
Error:编译时错误或系统错误
-
出现错误,必须修改源代码,程序才能继续执行
-
-
4.常见的异常
-
Exception:所有异常的基类
-
ArithmeticException:计算异常
-
ArrayIndexOutOfBoundsException:数组下标越界异常
-
NullPointerException:空指针异常
-
ClassCastException:类转换异常
-
InputMismatchException:输入不匹配异常
-
ClassNotFoundException:无法加载某个类
-
NumberFormatException:数字格式转换异常
5.try-catch-finally,处理异常的第一种方式
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//try包含可能发生异常的代码
try {
System.out.println("请输入被除数:");
int num1 = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
System.out.println(String.format("%d / %d = %d", num1, num2, num1 / num2));
} catch (InputMismatchException ex) {
//一旦出现输入不匹配异常,程序不会中断,会进入该catch中
//给用户看
System.out.println("请输入合理的数字");
//打印报错信息
ex.printStackTrace();
} catch (ArithmeticException ex) {
System.out.println("除数不可以为0");
//输出详细异常信息
System.out.println(ex.getMessage());
//退出虚拟机
System.exit(1);//0正常退出,1异常退出
} catch (Exception e) {
//是所有异常的基类,任何异常都能捕获到
//三个catch的顺序不能变,子类在前,父类在后(小异常在前,大异常在后)
System.out.println("输入有误,请重新的输入");
} finally {
//最后的,放在最后,始终执行
//只有一种情况不会执行,就是还未执行到finally,就强制退出虚拟机了
System.out.println("欢迎使用本程序");
}
System.out.println("最后的内容");
}
-
try:用来包含可能发生异常的代码
-
catch:用来捕获可能出现的异常信息,小异常(子类)在前,大异常(父类)在后
-
finally:用来收尾的,放在最后,无论发生异常与否,代码都会执行,只有一种情况不会执行,就是还未执行到finally,就强制退出了虚拟机。
-
使用try-catch-finally,会有三种情况发生
-
程序没有发生异常,不会进入到任何一个catch中,会执行finally中的代码及之后的代码
-
程序发生异常并且捕获到了,会进入到对应的catch中进行相应处理,然后再执行finally中的代码及之后的代码
-
程序发生异常,但是没有捕获到,只会执行finally中的代码
-
-
catch中的异常处理信息
-
加入自定义的提示语言
-
打印具体的报错信息
-
void printStackTrace(): 输出异常的堆栈信息(常用)
-
String getMessage(): 返回异常信息的描述字符串,是printStackTrace()输出信息的一部分
-
-
-
catch可以有多个
-
一段代码可能发生多种异常,可以使用不同的catch块分别捕获
-
依次从上往下进行匹配,一旦匹配上一个之后,其他的不再判断
-
catch顺序:先特殊,再普通,先子类,再父类
-
-
finally
-
退出java虚拟机时不执行
-
System.exit(0):正常退出
-
System.exit(1):非正常退出
-
-
6.throws,处理异常的第二种方式
public static int divide()
throws InputMismatchException, ArithmeticException, Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入被除数:");
int num1 = input.nextInt();
System.out.println("请输入除数:");
int num2 = input.nextInt();
return num1 / num2;
}
//调用抛出异常的方法需要对其声明的异常进行处理
//处理方式有两种
//第一种:try-catch,catch块中捕获的异常必须能够匹配使用throws关键字抛出的异常
public static void main(String[] args) {
try {
int num = divide();
} catch (Exception e) {
e.printStackTrace();
}
}
//第二种方式:在方法的声明处继续声明抛出异常,代码出现异常后,程序直接中断
public static void main(String[] args) throws Exception {
int num = divide();
System.out.println("商是" + num);
}
-
注意:
-
throws关键字只能必须写在方法声明处
-
throws关键字后面声明的异常必须是Exception或者是Exception的子类
-
如果方法的内部抛出了多个异常,那么throws后面也必须声明多个异常
-
如果抛出的多个异常有父子类关系,那么直接声明父类异常即可
-
-
如果调用了一个抛出异常的方法,我们就必须处理声明的异常
-
要么继续使用throws将异常抛出,交给方法的调用者处理,最终交给jvm
-
要么使用try-catch自己处理异常
-
-
7.throw,自定义异常进行抛出
public class Student {
private String name;//姓名
private String sex;//性别
public Student() {
}
public void setSex(String sex) throws Exception {
if ("男".equals(sex) || "女".equals(sex)) {
this.sex = sex;
} else {
throw new InputMismatchException("性别只能是“男”或“女”");
}
}
}
-
throw用在代码中,自定义要抛出的异常。throw new Exception("异常信息")
-
如果自定义的是编译时异常,需要在方法的声明处添加throws声明异常
-
调用方法时,使用try-catch捕获异常
-
public static void main(String[] args) { Student student = new Student(); try { student.setSex("dd"); } catch (Exception e) { e.printStackTrace(); } }
-
catch的异常类型要和方法声明的异常类型相匹配(相同或包含)
-
-
注意:
-
throw关键字必须写在方法的内部
-
throw关键字后面new的对象必须是Exception或者Exception的子类
-
throw关键字抛出指定的异常对象,就必须处理声明的异常
-
如果创建的是运行时异常,可以不处理,交给jvm
-
如果创建的是编译时异常,我们必须处理这个异常,要么try-catch,要么throws
-
-
8、日志工具log4j
-
系统真正部署到用户处之后,无法使用控制台查看报错信息,我们需要将用户的关键操作以及报错信息记录到日志文件中
-
log4j是第三方提供的专门记录日志的一个工具
-
我们在使用时需要将其引入,也就是将jar包加载到我们的项目中
-
-
使用步骤
-
引入jar包:在项目目录下创建lib文件夹,将jar包复制到lib目录下,右键lib目录,选择add as Library
-
在src下创建配置文件:log4j.properties
-
在文件中指定相关信息
-
### 设置Logger输出级别和输出目的地 ### # 输出级别从高到低是:error、warn、info、debug 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 ### 把日志信息输出到文件:test.log ### log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=test.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
-
-
使用log4j
-
创建日志对象:
-
引入的是:import org.apache.log4j.Logger;
-
private static Logger logger = Logger.getLogger(TestTry.class.getName());
-
-
使用相关方法记录日志信息
public class TestTry { //创建日志对象 private static Logger logger = Logger.getLogger(TestTry.class.getName()); public static void main(String[] args) { Scanner input = new Scanner(System.in); //try包含可能发生异常的代码 try { System.out.println("请输入被除数:"); int num1 = input.nextInt(); //记录用户操作 logger.info("输入了被除数:" + num1); System.out.println("请输入除数:"); int num2 = input.nextInt(); logger.debug("输入了除数:" + num2); System.out.println(String.format("%d / %d = %d", num1, num2, num1 / num2)); logger.debug("结果是:" + num1 / num2); } catch (InputMismatchException ex) { //一旦出现输入不匹配异常,程序不会中断,会进入该catch中 //给用户看 System.out.println("请输入合理的数字"); //打印报错信息 ex.printStackTrace(); logger.error("用户输入的不是数字"); } catch (ArithmeticException ex) { System.out.println("除数不可以为0"); //输出详细异常信息 System.out.println(ex.getMessage()); logger.error("用户输入了0做除数"); System.exit(1); } catch (Exception e) { //是所有异常的基类,任何异常都能捕获到 //三个catch的顺序不能变,子类在前,父类在后(小异常在前,大异常在后) System.out.println("输入有误,请重新的输入"); } finally { //最后的,放在最后,始终执行 //只有一种情况不会执行,就是还未执行到finally,就强制退出虚拟机了 System.out.println("欢迎使用本程序"); } System.out.println("最后的内容"); } }
-
-