异常处理:
Java异常处理的关键字有:try catch finally throw throws
错误不是异常,而是脱离程序员控制的问题,所有的异常类是从java.lang.Exception类继承的子类。
异常发生的原因通常包含:
用户输入了非法的数据
要打开的文件不存在
网络通信时连接中断,或者JVM内存的溢出。
try catch结构的语法:
public class Test { 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)); System.out.println("感谢使用本程序!"); } catch (Exception e) { System.err.println("产生了异常信息"+e.getMessage());//e.getMessage()获得异常部分信息 } System.out.println("try catch块后面的代码"); } }
需要注意的是,在上例中,当除数为0时,程序会产生异常。此时try catch块后面的代码会正常输出。程序运行结果为:
请输入被除数:2 请输入除数:0 产生了异常信息/ by zero try catch块后面的代码
e.getMessage()为获得异常部分信息。即在本例中输出的是:/ by zero
try与catch与finally结构
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)); System.out.println("感谢使用本程序!"); } catch (Exception e) { }finally{ System.out.println("这里是finally块"); } }
需要注意的是,唯一不运行finally的情况就是退出JVM,即System.exit(0); 当catch语句里有return时,先运行finally,最后执行return语句。finally不管是否产生异常,都会执行其中的代码。上例中运行结果为:
请输入被除数:4 请输入除数:0 这里是finally块
多重try catch块
多重try catch块有以下特征:排列catch语句的顺序:先子类后父类;发生异常时按照顺序逐个匹配;只执行第一个与异常类型匹配的catch语句。语法结构为:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}
throws/throw关键字
如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。下个实例中,抛出了一个RemotException异常,一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
public class className { public void deposit(double amount) throws RemoteException { throw new RemoteException(); } }
处理异常时有以下注意事项:catch 不能独立于 try 存在。在 try/catch 后面添加 finally 块并非强制性要求的。try 代码后不能既没 catch 块也没 finally 块。try, catch, finally 块之间不能添加任何代码。
记忆:(常见的异常类型)
Exception:异常层次结构的父类
ArithmeticException:算术错误情形,如以零作除数
ArrayIndexOutOfBoundsException:数组下标越界
NullPointerException:尝试访问null对象成员
ClassNotFoundException:不能加载所需的类
IIIegalArgumentException:方法接收到非法参数
ClassCastException:对象强制;类型转换出错
NumberFormatException:数字格式转换异常,如把“abc”转换成数字
日志
需要先导入一个Jar包,以下实例为创建一个日志对象,然后存放异常信息并显示到控制台:
public static void main(String[] args) { //创建一个日志对象 Logger logger=Logger.getLogger("测试类Test"); Scanner input=new Scanner(System.in); try { System.out.println("请输入被除数"); int a = input.nextInt(); System.out.println("请输入除数"); int b = input.nextInt(); System.out.println("结果:" + a / b); } catch (ArithmeticException e) { //日志存放错误信息 logger.debug(" 除数不能为0"); } catch (Exception e) { //日志存放错误信息 logger.debug(" 输入的不是数字"); } }
log4j.properties配置文件源码为:
### 设置Logger输出级别和输出目的地 ### 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.PatternLayout log4j.appender.stdout.layout.ConversionPattern =%p %d{yyyy-MM-dd HH:mm:ss SSS} %l%m%n ### 把日志信息输出到文件:jbit.log ### log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=jbit.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
输出结果为:
请输入被除数 54 请输入除数 0 DEBUG 2018-03-28 19:11:08 639 com.log.Test.main(Test.java:21) 除数不能为0
日志文件会实时记录异常信息:
2018-03-28 17:31:04com.log.Test.main(Test.java:25) Test.java DEBUG 输入的不是数字 2018-03-28 18:18:39com.log.Test.main(Test.java:21) Test.java DEBUG 除数不能为0 2018-03-28 19:11:08com.log.Test.main(Test.java:21) Test.java DEBUG 除数不能为0 2018-03-28 19:11:56com.log.Test.main(Test.java:21) Test.java DEBUG 除数不能为0