java第九天---异常处理和日志
一、异常处理
1、什么是异常?
异常是指程序运行时产生的异常事件,通常是由外部问题(如硬件错误)所导致的。在java等面向对象的编程语言中异常属于对象。
2、异常体系
thorwable:所有异常的祖宗 error:错误,致命性错误 -> vritualMachineException -> ServiceConfigurationException -> ThreadDeath exception:编译器异常 ->RuntimeException ->NullPointException ->ArithmeticException ->InputMismatchException ->ArrayIndexOutOfBoundsException ->MissingResourceException ->IOException ->FileNotFoundException ->ObjectStreamException ->EOFException ->ClassNotFoundException ->SQLExcepiton
error:该类异常是比较严重的错误,一般指jvm错误,仅靠程序本身无法更改。
exception:编译器异常,在编写程序时出现的异常。子类RuntimeException异常,是程序运行时出现的异常,将异常处理处理掉,程序下边代码还能与 运行
3、异常处理的作用
不至于让程序因为一些不致命的错误而导致不能运行
4、处理异常的方法有两类:
抛出异常、异常捕获
5、抛出异常 --- throw、throws
throw:抛出方法中可能出现的异常对象。如果是非RuntimeException,需要在方法的声明时加上该异常的抛出(throws语句)或者在方法中对异常 进行处理try---catch语句,否则编译报错。
throws:在方法的尾部用来声明方法中可能出现的异常,抛给调用者进行异常,或者调用者选择继续抛出,如果都不处理,则抛出到虚拟机,程 序无法运行。
示例一:异常抛出
public class ArrayUtil { //获取数组中的最大值 public static int arrMax(int[] arr){ if(arr==null) throw new NullPointerException("数组为空"); if(arr.length==0) throw new ArrayIndexOutOfBoundsException("数组长度为零"); int max=arr[0]; for(int i=0;i<arr.length;i++){ if(arr[i]>max){ max=arr[i]; } } return max; } }
public class DemoTest { public static void main(String[] args) { int[] arr={10,35,61}; int[] arr1={}; ArrayUtil.arrMax(arr1); System.out.println(arr.length); } }
此例仅是异常抛出,并没有异常处理。导致出现异常后,程序直接停止
示例二:throws抛出异常
public class DateFormat { public static void main(String[] args) throws ParseException { String ss="2019-09-12 dsfsdf 12:12:12"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date parse = simpleDateFormat.parse(ss); System.out.println(parse); } }
该例中,将异常抛给mian()方法,再将异常抛给虚拟机,出现错误时,程序直接停止。
throws语句将异常抛给调用者(方法)--->往上抛------>往上抛---->main()--->jvm虚拟机,在到达虚拟机之前如果没有处理,程序停止
示例:
public class DateF { // 方法名后的throws将异常抛给调用者 public static Date getDate(String str) throws ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date parse = simpleDateFormat.parse(str); return parse; } }
public class DateTest { //main方法中调用有异常抛出的方法,然后再main方法中抛给jvm public static void main(String[] args) throws ParseException { String ss="2019-09-12 dsfsdf 12:12:12"; Date date = DateF.getDate(ss); System.out.println(date); } }
6、try-catch 捕获并解决
思考:我们以前的程序中只要出错,就会停止,这样是不行的。我们不能因为一点不致命的错误就让整个程序停止,所以我们可以将一些异常进行处理。
异常处理的格式:Exception是所以异常的父类。 try{代码块①}catch(Exception e){代码块②:异常处理}
流程:当代码块①没有异常时,此处后边的代码正常执行。如果代码块①有异常,就会先执行代码块②。然后接着执行try--catch后的代码。
示例:
public class DateF { // 方法名后的throws将异常抛给调用者 public static Date getDate(String str) throws ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date parse = simpleDateFormat.parse(str); return parse; } }
public class DateTest { public static void main(String[] args){ String ss="2019-09-12 dsfsdf 12:12:12"; Date date = null; //异常不再抛出,使用try-catch处理 try { date = DateF.getDate(ss); } catch (ParseException e) { e.printStackTrace(); } System.out.println(date); }
7、多重catch
多重catch中,catch只会执行一个。代码块中可能有多个异常,可以通过多个catch进行捕获,异常存在父子关系,但是子类是放在父类之前的
public class DateF { // 方法名后的throws将异常抛给调用者 public static Date getDate(String str) throws ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date parse = simpleDateFormat.parse(str); return parse; } }
public class DateTest { public static void main(String[] args){ String ss="2019-09-12 dsfsdf 12:12:12"; Date date = null; int a=10; int b=12; int c=0; try { //这里可能有异常 date = DateF.getDate(ss); //这里也可能有异常 c=a/0; } catch (ParseException e) { e.printStackTrace(); }catch (ArithmeticException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } System.out.println(date); System.out.println(c); } }
黑色箭头标识运行顺序,红色箭头标识异常关系,黄色箭头标识发生异常时对应的catch
运行结果:
finally关键字:可以关闭io,数据库连接
try { date = DateF.getDate(ss); c=a/0; } catch (ParseException e) { e.printStackTrace(); }catch (ArithmeticException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); }finally { //finally是必然会执行的,一般用来关闭io流,关闭数据库连接 System.out.println("jieshu"); }
8、自定义异常类型
①我们可以自定义一些异常类型来根据我们的场景进行运用。
②定义格式
权限修饰符 class 类名 extends Exception{
public 类名(String msg){//构造方法,msg提示类型错误信息
super(msg);
}
};
③示例:定义一个Person类,类中有一个性别属性,我们要保证输入的属性值为男或女,不然就爆出异常,程序继续向下执行
package com.fy.day09.demo3; public class Person { private int age; private String name; private String sex; public Person() { } public Person(int age, String name, String sex) { this.age = age; this.name = name; this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) throws SexException { if("男".equals(sex) || "女".equals(sex)){ this.sex = sex; }else { throw new SexException("性别必须为男或女"); } } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + ", sex='" + sex + '\'' + '}'; } }
public class SexException extends Exception{ public SexException(String msg){ super(msg); } }
public class DemoTest { public static void main(String[] args) { Person p = new Person(); p.setAge(19); p.setName("小红"); try { p.setSex("dsf"); } catch (SexException e) { e.printStackTrace(); } System.out.println(p); } }
二、日志
1、日志类的作用
可以帮我们记录程序的运行记录,比如某时谁登录,做了那些操作
2、使用日志类
①在项目中添加log4j.jar包
项目的src文件夹上--->右键-新建文件夹或包lib
将jar文件拷贝到lib目录中
lib目录上右键-【Add as LIbrary】
②在项目中添加日志配置文件
log4j.properties:
### 把日志信息输出到控制台 ### 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-MM-dd HH:mm:ss} %m%n ### 把日志信息输出到文件:anbo.log ### log4j.appender.file=org.apache.log4j.FileAppender #指定输出目录 log4j.appender.file.File=AAA.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n ### 设置优先级别、以及输出源 ### log4j.rootLogger=info,stdout,file
③使用
public class DemoTest { public static void main(String[] args) { Logger demoTest = Logger.getLogger("DemoTest"); //获取日志对象 demoTest.info("info级别日志"); demoTest.warning("warn级别"); } }
Debug->debug调试级别的日志
INFO->info正常级别的日志
WARN->warn警告级别的日志
ERROR->error错误级别的日志
FATAL->fatal致命级别的日志
在配置文件中,log4j.rootLogger后设置的优先级别越高,打印的日志信息越少,设置为fatal的话,则其余四个均不能打印