java.lang包里的Throwable类有两个重要的子类:Exception(异常)和Error(错误)
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
Exception(异常):是程序本身可以处理的异常。Exception 类有一个重要的子类 RuntimeException。RuntimeException 异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出该异常)和 ArrayIndexOutOfBoundsException (下标越界异常)
Throwable类常用方法
1.public string getMessage():返回异常发生时的详细信息
2.public string toString():返回异常发生时的简要描述
3.public string getLocalizedMessage():返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
4.public void printStackTrace():在控制台上打印Throwable对象封装的异常信息
异常处理总结
try 块: 用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch 块: 用于处理try捕获到的异常。
finally 块: 无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行
在以下4种特殊情况下,finally块不会被执行:
1.在finally语句块第一行发生了异常。 因为在其他行,finally块还是会得到执行
2.在前面的代码中用了System.exit(int)已退出程序。 exit是带参函数 ;若该语句在异常语句之后,finally会执行
3.程序所在的线程死亡。
4.关闭CPU。
抛出异常:一个方法不处理这个异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理
系统会自动抛出异常,比如除0这样的操作,包括空指针这样的
throw:将产生的异常抛出(强调是动作),抛出的既可以是这个异常的引用,也可以是异常对象(在方法体内)
throws:一个方法可能出现异常,但又没有能力处理这种异常,在方法声明出用throws抛出异常
注意 : 调用可能会抛出异常的方法,必须添加try-catch代码块尝试去捕获异常 或者 添加throws 声明 来将异常 抛出给更上一层的调用者进行处理,这里需要注意一个细节:新的异常包含原始异常的所有信息,根据这个我们可以去追溯最初异常发生的位置
自定义异常:
自定义异常可以对我们需要判断的某些异常做专门的捕获。比如空指针。或者数值转换异常。等等。我们都会根据对应的异常给予用户相应的提示信息。让用户知道自己是不是做错了什么操作。还有当我们捕获到对应的异常。那我们能够根据这个异常做相关的后续操作,比如在事务中我们可以通过定义异常来回滚。
自定义的异常类:继承Exception类
public class MyException extends Exception { public MyException() { } public MyException(String s) { super(s); } }
一个可能抛出异常的方法:
public class ExceptionClass { public String setNumber(int number) throws MyException { if(number >= 0 && number <=100) { return "正常"; } else { throw new MyException("输入错误"); } } }
在主类中调用
public class MainClass { public static void main (String args[]) { try{ ExceptionClass exception = new ExceptionClass(); //设置0-100范围数字 String s = exception.setNumber(90); System.out.println(s); } catch(MyException e) { System.out.println("异常信息为:"+e.getMessage()); } } }
会依次编译MyException.java->ExceptionClass.java->MainClass.java
利用Aop的思想定义一个统一处理异常的切面类:避免在controller方法中反复用try/catch来捕获
封装异常信息的类:
public class ExceptionInfo { private String className; private String methodName; private Date logTime; //异常记录时间 private String message;//异常信息 //.....其他属性 //省略set get }
统一处理异常的切面类:
@Aspect public class ExceptionMonitor { /** * 定义异常监控类 */ @Pointcut("连接点")void exceptionMethod() { } @Around("exceptionMethod()") public Object monitorMethods(ProceedingJoinPoint thisJoinPoint) { try { return thisJoinPoint.proceed(); } catch (Throwable e) { ExceptionInfo info=new ExceptionInfo(); //异常类记录 info.setClassName(thisJoinPoint.getTarget().getClass().getName()); info.setMethodName(thisJoinPoint.getSignature().getName()); info.setLogTime(new Date()); info.setMessage(e.toString()); //上传日志系统,自行完善 //ExceptionReportUtils.report(info); return null; } } }
就可以自动将接口方法中出现的异常全部保存到日志系统中