程序中的异常
在Java中,程序一旦出现异常就会立刻结束,语句将不会被执行,一般我们通过if-else语句来对各种异常进行判断处理,这是在“使用Java理解逻辑程序中学到的”代码如下:
public class Test2 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.print("请输入被除数:");
int num1=0;
if(in.hasNextInt()){
num1=in.nextInt();
}else{
System.out.println("输入的被除数不是整数,程序退出");
System.exit(1);
}
System.out.print("请输入除数:");
int num2=0;
if(in.hasNextInt()){
num2=in.nextInt();
if(0==num2){
System.out.println("输入的除数是0,程序退出");
System.exit(1);
}
}else{
System.out.println("输入的被除数不是整数,程序退出");
System.exit(1);
}
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序!");
}
}
但是用过上面的代码我们可以看出代码非常臃肿所以以下总结了if-else的主要缺点:
1.代码臃肿,加入了大量的异常情况判断和处理代码。
2.程序员把相当多的精力放在了处理异常代码上,放在了“堵漏洞”上,减少了编写业务代码的时间,必然影响开发效率。
3.很难穷举所有的异常情况,程序人仍就不健壮。
4.异常处理代码和业务代码交织在一起,影响代码的可读性,加大日后程序的维护难度。
对于上面的问题,Java有专门处理异常的异常处理程序,就是我们今天要介绍的异常。
什么是异常:
异常就是在程序的运行过程中发生的不正常的事件,如所需文件找不到,网络连接不通或终端,算数运算出错,数组下标越界等,异常会中断正在运行的程序
什么是异常处理:
异常处理机制就像我们对平时会遇到的意外情况,预先想好了一些处理的办法,也就是说程序执行代码的时候,万一发生了异常。程序会按照预定的处理办法对异常进行处理,异常处理完毕之后,程序继续执行。
Java的异常处理通过五个关键字实现:try,catch,finally,throw,throws
try-catch块
public class Test3 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.print("请输入被除数:");
try{
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.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
e.printStackTrace();
}
}
}
可能出现的三种情况:
1.如果try块中的所有语句正常执行完毕,不会发生异常,那么catch块中的所有语句都将会被忽略。
2…如果try语句块在执行过程中遇到异常,并且这个异常与catch中声明的异常类型相匹配,那么try块其余剩下的代码都将被忽略
3.如果try语句块在执行过程中遇到异常,而抛出的异常在catch块里面没有被声明,那么程序立刻退出。
常用的调用的异常对象的方法输出异常信息有以下两种
void printStackTrace(),输出异常的堆栈信息。
String getMessage(),返回异常信息描述字符串。
try-catch-finally块
public class Test4 {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.print("请输入被除数:");
try{
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.out.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
System.out.println(e.getMessage());
}finally{
System.out.println("感谢使用本程序");
}
}
}
可能出现的两种情况:
1.如果try块中所有语句正常执行完毕,那么finally块就会被执行。
2.如果try语句块在执行过程中遇到异常,无论这种异常能否呗catch块捕捉到,都将执行finally块中的代码。
特别注意即使在try块和catch块中存在return语句,finally类块中的语句也会被执行,发生异常时的执行顺序:执行try块或catch块中return之前的语句,执行finally块中的语句,执行try块或catch中的return语句退出。
finally唯一不被执行的情况:在异常处理代码中执行System.exit(1),将退出Java虚拟机。
多重catch块
一段代码可能会引发多种类型的异常,这是,可以在一个try语句快后面放多个catch块,分别处理不同的异常,但顺序必须是从子类到父类,最后一个一般都是Exception类。
声明异常-throws:
Java中通过关键字throws声明某个方法可能抛出的各种异常,throws可以同时声明多个异常,之间用逗号隔开。
/**
* 使用throws抛出异常。
*/
public class Test7 {
/**
* 通过try-catch捕获并处理异常。
* @param args
*/
public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"
+ "除数不能为零");
e.printStackTrace();
}
}
// /**
// * 通过throws继续声明异常。
// */
// public static void main(String[] args) throws Exception {
// divide();
// }
/**
* 输入被除数和除数,计算商并输出。
* @throws Exception
*/
public static void divide() throws Exception {
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));
}
}
抛出异常-throw
public class Person {
private String name = "";// 姓名
private int age = 0;// 年龄
private String sex = "男";// 性别
/**
* 设置性别。
* @param sex 性别
* @throws Exception
*/
public void setSex(String sex) throws Exception {
if ("男".equals(sex) || "女".equals(sex))
this.sex = sex;
else {
throw new Exception("性别必须是“男”或者“女”!");
}
}
public void setAge(int age) throws Exception {
if (age>=0 && age<=100)
this.age= age;
else {
throw new Exception("年龄必须是1-100!");
}
}
/**
* 打印基本信息。
*/
public void print() {
System.out.println(this.name + "(" + this.sex
+ "," + this.age + "岁)");
}
}
/*
* 捕获throw抛出的异常
*/
public class Test9 {
public static void main(String[] args) {
Person person = new Person();
try {
person.setSex("Male");
person.print();
person.setAge(11);
person.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
throw和throws的区别
1.作用不同:throw用于在程序中抛出异常;throws用于声明在该方法内抛出了异常。
2.使用的位置不同:throw位于方法内部,可以作为单独语句使用;throws必须狠宰方法参数列表的后面,不能单独使用。
3.内容不同:throw抛出一个异常对象,而且只能是一个;throws后面跟异常类,而且可以跟多个异常类。
日志分类
主要分成三类:
1.SQL日志,记录系统执行的SQL语句
2.异常日志,记录系统运行中发生的异常事件
3.业务日志,记录系统运行过程,如用户登录,操作记录。
常用的配置参数及含义
1.%d,用来设置输出日志的日期和时间
2.%m,用来输出代码中的指定消息
3.%n,用来输出一个回车换行符
4.%l,用来输出日志事件的发声位置,包括类名,发生的线程,以及在代码中的行数
5.%p,用来输出优先级
6.%f,用来输出文件名
7.%m,用来输出方法名