1.概述
异常,这两个字大家想到的一定是发生了不是正常以外的事情,就好比如我去超市买东西,正常的流程是:进超市、选东西、结账、回家。结果在结账的时候出现了一些小插曲,平常都是用手机支付的,但结果没有带手机,这是生活中的异常。
程序中的异常:
import java.util.*;
public class Test3 {
public static void main(String[] args) {
Scanner ss=new Scanner(System.in);
System.out.print("请输入被除数");
int num1=ss.nextInt();
System.out.print("请输入除数");
int num2=ss.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序");
}
}
如果在这里输入正常的数:8,2打印结果
但是如果输入其他的字符,打印结果又会是什么呢?
2.try-catch
如上述图所示,会出现一些看不懂的异常,那如何去处理这些异常呢?这里我们会使用try-catch来处理这些
import java.util.*;
/**
* 使用try-catch进行处理异常
*
* */
public class Test3 {
public static void main(String[] args) {
Scanner ss=new Scanner(System.in);
System.out.print("请输入被除数");
try {
int num1=ss.nextInt();
System.out.print("请输入除数");
int num2=ss.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序");
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数"+"除数不能为0");
e.printStackTrace();
}
}
}
3.异常的类型
4.try-catch-finally
1.使用 try-catch-finally的话如果try代码块的代码正常执行,catch的代码不会执行,而finally里的代码会执行。
2.try的代码没有正常执行,便会执行catch的代码,但是finally里的代码也会执行。
import java.util.Scanner;
/**
* 使用try-catch-finally进行处理异常
*
* */
public class Test4 {
public static void main(String[] args) {
Scanner ss=new Scanner(System.in);
System.out.print("请输入被除数");
try {
int num1=ss.nextInt();
System.out.print("请输入除数");
int num2=ss.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数"+"除数不能为0");
System.out.println(e.getMessage());
}finally{
System.out.println("感谢使用本程序");
}
}
}
如果在try里面或者catch里加上return的话,finally也是会执行,除非是加上System.exit(1);这句会直接结束整个应用程序
5.多重catch块
一段代码里是会出现不同的异常的,这个时候可以在try的后面加上多条catch块,会以不同的异常来报出不同的错误,但是有点规范,最后一个异常一般都是Exception类因为所有异常子类都继承自Exception,但是把父类的异常放在最前面的话后面的异常就不会有作用了。
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* 测试多重catch块
*
* */
public class Test7 {
public static void main(String[] args) {
Scanner ss=new Scanner(System.in);
System.out.print("请输入被除数");
try {
int num1=ss.nextInt();
System.out.print("请输入除数");
int num2=ss.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
}catch (InputMismatchException e){
System.out.println("被除数和除数必须是整数");
}catch(ArithmeticException e){
System.out.println("除数不能为0");
}catch (Exception e) {
System.err.println("其他未知异常");
}finally{
System.out.println("感谢使用本程序");
}
}
6.声明异常----throws
如果在一个方法体重抛出了异常,我们就希望调用者能够及时的捕获异常,那么如何通知调用者呢?Java语言中通过throws关键字声明某个方法可能抛出的各种异常。throws可以同时声明多个异常.
处理方法的异常
1.通过使用try-catch捕获处理异常
2.继续使用throws抛出异常,可以交给JVM(JAVA虚拟机)来处理
import java.util.*;
/**
* 使用throws声明异常
* */
public class Test8 {
/**
* 通过try-catch捕获处理异常
* @param args
* */
public static void main(String[] args) {
try {
divide();
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
e.printStackTrace();
}
}
/**
* 输入被除数和除数,计算商并输出
* @throws Exception
* */
public static void divide() throws Exception{
Scanner ss=new Scanner(System.in);
System.out.print("请输入被除数:");
int num1=ss.nextInt();
System.out.print("请输入除数:");
int num2=ss.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
}
}
7.抛出异常----throw
java中可以使用throw关键字自行抛出异常,为什么抛出异常:由于在当前环境中无法解决参数问题,因此在方法体内通过throw抛出异常,把问题交给调用者区解决。
/**
* 使用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 print(){
System.out.println(this.name+"("+this.sex+","+this.age+"岁)");
}
}
测试类
/**
* 测试类抛出异常
* */
public class Test9 {
public static void main(String[] args) {
Person p=new Person();
try {
p.setSex("张三");
p.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里说明throws和throw的区别表现
1。作用不同:throw用于在程序中抛出异常;throws用于方法声明在该方法内抛出了异常。
2.使用的位置不同:throw位于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
3.内容不同:throw抛出一个异常对象,而且只能是一个;throws后面跟异常类,儿子可以跟多个异常类。
8.开源日志记录工具log4j
1.使用步骤
(1)在项目中加入log4j所使用的JAR文件
(2)创建log4j.properties文件
(3)编写log4j.properties文件,配置日志信息
(4)在程序中使用log4j记录日志信息
2.日志及分类
SQL日志:记录系统执行的SQL语句
异常日志:记录系统运行中发生的异常事件
业务日志:记录系统运行过程,如用户登录、操作记录
3.路径
log4j的JAR包:apache-log4j-1.2.17\log4j-1.2.17.jar
使用手册:apache-log4j-1.2.17\site\manual.html
JavaDoc:apache-log4j-1.2.17\site\apidocs\index.html
#log4j.rootLogger=error,stdout#
#log4j.appender.stdout=org.apache.log4j.ConsoleAppender#
#log4j.appender.stdout.Target=System,err#
#log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout#
log4j.rootLogger=debug,stdout,wenjian,wenjian2,wang
#???????????
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-M-d HH\:mm\:ss}%x[%5p](%C\:%M) %m%n
#???????
log4j.appender.wenjian=org.apache.log4j.FileAppender
log4j.appender.wenjian.File=abc.log
log4j.appender.wenjian.layout=org.apache.log4j.PatternLayout
log4j.appender.wenjian.layout.ConversionPattern=%d{yyyy-M-d HH\:mm\:ss}%x[%5p](%C\:%M) %m%n
log4j.appender.wenjian2=org.apache.log4j.FileAppender
log4j.appender.wenjian2.File=abc2.log
log4j.appender.wenjian2.layout=org.apache.log4j.PatternLayout
log4j.appender.wenjian2.layout.ConversionPattern=%d{yyyy-M-d HH\:mm\:ss}%x[%5p](%C\:%M) %m%n
log4j.appender.wang=org.apache.log4j.FileAppender
log4j.appender.wang.File=wang.html
log4j.appender.wang.layout=org.apache.log4j.HTMLLayout
代码文件
import org.apache.log4j.Logger;
public class Log {
private static Logger logger=Logger.getLogger(Log.class);
public static void main(String[] args) {
logger.debug("Debug信息!");
logger.debug("Debug信息!");
logger.debug("Debug信息!");
logger.debug("Debug信息!");
logger.info("info信息!");
logger.info("info信息!");
logger.info("info信息!");
logger.info("info信息!");
logger.warn("warn信息!");
logger.warn("warn信息!");
logger.warn("warn信息!");
logger.warn("warn信息!");
logger.error("error信息!");
logger.error("error信息!");
logger.error("error信息!");
logger.error("error信息!");
logger.fatal("fatal信息!");
logger.fatal("fatal信息!");
logger.fatal("fatal信息!");
logger.fatal("fatal信息!");
}
}
1.基本划分
fatal>error>warn>info>debug
2.日志输出目的地Appender
这里的debug是日志里输出的和debug同级或者比它大的信息
后面的logfile是以文件后缀名log的形式出现
log4j.rootLogger=debug,stdout,logfile
3.日志分布类型Layout
Appender必须使用一个与之相关的布局类型Layout,用来指定输出样式。log4j中最常用的Layout的有以下三种
1.HTMLLayout:格式化日志输出为HTML表格形式
2.SimpleLayout:以一种非常简单的方式格式化日志输出,它的输出级别Level,然后跟着一个破折号“—”,最后是日志消息
3.PatternLayout:根据指定的转换模式格式化日志输出,从而支持丰富多样的输出格式。需要配置,layout.ConversionPattern属性若没有配置该属性,则使用默认的转换模式。
4.转换模式ConversionPattern
%d:用来设置输出日志的日期和时间,默认格式为IS08601。也可以再其后指定格式:%d{yyyy-MM-dd HH:mm:ss}
%m:用来输出代码中的指定的消息
%n:用来输出一个回车换行符
%l:用来输出日志时间的发生位置,包括类名、发生的线程,以及代码中的行数
%p:用来输出优先级,及debug、info、warn、error、fatal等
%F:用来输出文件名
%M:用来输出方法名