一,基本概念

  异常是程序在运行时出现的不正常情况。是Java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。
  异常处理的目的是提高程序的健壮性。你可以在catch和finally代码块中给程序一个修正机会,使得程序不因不可控制的异常而影响程序的流程。同时,通过获取Java异常信息,也为程序的开发维护提供了方便。
Java异常类层次结构图

Java中的异常用对象来处理,并定义java.lang.Throwable作为所有异常的超类。Throwable分成了两个不同的分支,Exception(异常)和 Error(错误);

其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常。或不受检查异常(Unchecked Exception)和检查异常(Checked Exception);

异常是针对 方法 来说的,抛出、声明抛出、捕获和处理异常都是在方法中进行的;

Java异常处理通过5个关键字try、catch、throw、throws、finally进行管理;

Error(错误):灾难性的致命的错误,是程序无法控制和处理的。

  Error类对象由 Java 虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。例如,Java虚拟机运行错误、内存溢出。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;还有发生在虚拟机试图执行应用时,如类定义错误、链接错误。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。
Exception(异常):通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。。

运行时异常和受检查异常

运行时异常 (unChecked异常):

  RuntimeException类及其子类都被称为运行时异常。这些异常一般是由程序逻辑错误引起的,属于应该解决的Bug,程序应该从逻辑角度避免这类异常的发生,不推荐try-catch来捕获处理,但是有时候为了增强用户体验,保证Crash次数降到最低,会人为捕捉一些运行时异常。这种异常的特点是Java编译器不去检查它,也就是说,当程序中可能出现这类异常时,即使没有用try-catch语句捕获它,也没有用throws字句声明抛出它,还是会编译通过。但在运行时会被系统自动抛出。
非运行时异常 (checked异常):

  除了RuntimeException类及其子类外,其他的Exception类及其子类都属于非运行时异常,从程序语法角度讲是必须进行处理的异常,如果不处理程序就不能编译通过。
异常转型和异常链:

  我们做的JEE项目时候,一般会有三层的结构:持久层、逻辑层、展现层。异常也是如此的,当我们各个层之间传递异常,我们就需要先封装,然后传递。
异常链示例

catch (SQLException e)
{
throw new JdbcException(e);
}

二、异常处理机制

  在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常
  当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
  该方法的调用者必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,所经方法都层层上抛获取的异常,若最终都没有被处理,将交由虚拟机处理。处理也很简单,就是打印异常消息和堆栈信息,记录日志。
捕捉异常
  在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。
  运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,如果出现异常的线程为主线程,则整个程序运行终止;如果非主线程,则终止该线程,其他线程继续运行。
  在方法中用try-catch语句捕获并处理异常,catach语句可以有多个,用来匹配处理异常。并且尽量将捕获底层异常类的catch子句放在前面。
  异常总是先被抛出,后被捕捉的。
Java规定
  对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
  RuntimeException由业务逻辑保证。
3.1、抛出异常实例(throws 和 throw)

public class Throws
{
public static void main(String[] args) throws Exception
{//抛出异常类
System.out.println(10 / 0);
throw new Exception("抛出异常对象");
//System.out.println("throw后面的代码不再执行");
}
}

3.2、捕获异常实例(try-catch 和 finally)

import java.util.InputMismatchException;
import java.util.Scanner; public class TryCatch {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); try { //可能会发生异常的程序代码
System.out.print("请输入一个数字:");
int a = input.nextInt();
} catch (InputMismatchException e) {// 捕捉异常
System.err.println("数据类型不符!");
e.printStackTrace();
System.err.println(e.getMessage());
// return; 若捕捉到异常会先执行finally, 再return。
} catch (Exception e) {// catch 先写子类,再写父类
System.out.println("再捕捉一次!");
// System.exit(0);
} finally {// 除非执行System.exit(0),否则都会执行
System.out.println("finally 被执行!");
// 应用举例:确保关闭数据库,关闭流
} System.out.println("我还是被执行了!");
// 如果提前return,则不执行了
}
}

throw 和throws关键字的区别
throw用于抛出异常对象,后面跟的是异常对象;throw用在方法内。
throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在方法方法签名上。
通常情况:方法内容如果有throw,抛出异常对象,并没有进行处理,那么方法上一定要声明,否则编译失败。
三、Java常见异常

4.1、Error

LinkageError:链接错误;
ThreadDeath:线程死锁;
OutOfMemoryError:内存溢出;
StackOverflowError :堆栈溢出;
NoClassDefFoundError:类定义错误;
Virtual MachineError:虚拟机运行错误。
4.2、运行时异常(unChecked异常)

SecurityException:安全性异常;
NullPointerException:空指针异常;
ClassCastException:类型强制转换异常;
ClassNotFoundException:找不到类异常;
IllegalArgumentException:非法参数异常;
NegativeArraySizeException:数组长度为负异常;
ArithmeticException:算术条件异常。如:整数除零;
ArrayIndexOutOfBoundsException:数组下标越界异常;
ArrayStoreException:数组中包含不兼容的值抛出的异常;
StringIndexOutOfBoundsException:字符串下标越界异常;
ArrayStoreException:向数组中存放与声明类型不兼容对象异常;
4.3、非运行时异常(checked异常)

IOException:输入输出流异常;
SQLException:数据库操作异常;
EOFException:文件已结束异常;
TimeoutException:执行超时异常;
DataFormatException:数据格式化异常;
NoSuchFieldException:没有匹配的属性异常;
ClassNotFoundException:没有匹配的类异常;
FileNotFoundException:没有匹配的文件异常;
NoSuchMethodException:没有匹配的方法异常;
4.4、Throwable类的主要方法

public String getMessage():返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
public Throwable getCause():返回一个Throwable 对象代表异常原因。
public String toString():使用getMessage()的结果返回类的串级名字。
public void printStackTrace():打印toString()结果和栈层次到System.err,即错误输出流。
public StackTraceElement [] getStackTrace():返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
public Throwable fillInStackTrace():用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。
四、自定义异常实例

实例一:

class UserException extends Exception { // 继承父类
public UserException() {
super();
}
public UserException(String message) {
super(message);
}
} public void activatioin(String code) throws UserException {
try {
User user = userDao.findByCode(code);
if(user == null) throw new UserException("无效的激活码!");
if(user.isStatus()) throw new UserException("您已经激活过了");
userDao.updateStatus(user.getUid(), true); // 修改状态
} catch(SQLException e) {
throw new RuntimeException(e);
}
}

实例二:

package Test;
import java.lang.Exception;
public class TestException {
static int quotient(int x, int y) throws MyException { // 定义方法抛出异常
if (y < 0) { // 判断参数是否小于0
throw new MyException("除数不能是负数"); // 异常信息
}
return x/y; // 返回值
}
public static void main(String args[]) { // 主方法
int a =3;
int b =0;
try { // try语句包含可能发生异常的语句
int result = quotient(a, b); // 调用方法quotient()
} catch (MyException e) { // 处理自定义异常
System.out.println(e.getMessage()); // 输出异常信息
} catch (ArithmeticException e) { // 处理ArithmeticException异常
System.out.println("除数不能为0"); // 输出提示信息
} catch (Exception e) { // 处理其他异常
System.out.println("程序发生了其他的异常"); // 输出提示信息
}
} }
class MyException extends Exception { // 创建自定义异常类
String message; // 定义String类型变量
public MyException(String ErrorMessagr) { // 父类方法
message = ErrorMessagr;
} public String getMessage() { // 覆盖getMessage()方法
return message;
}
}

五、Java异常处理的原则和技巧

不要把自己能处理的异常抛给别人;
catch块尽量保持一个块捕获一类异常;
细化异常的类型,不要不管什么类型的异常都写成Excetpion;
避免过大的try块,不要把不会出现异常的代码放到try块里面;

如果把父类的异常放到前面,后面的catch语句块将得不到执行的机会;

尽量将异常统一抛给上层调用者,由上层调用者统一决定如何进行处理。
不要用try-catch参与控制程序流程,异常控制的根本目的是处理程序的非正常情况;
只要不是retry或者queue的情况,基本上所有的异常都是需要继续向上抛的,最终交给顶层异常处理机制(应用或者容器)。

Java异常处理三原则

具体明确

提早抛出

通过提早抛出异常(又称"迅速失败"),异常得以清晰又准确。堆栈信息立即反映出什么出了错(提供了非法参数值),为什么出错(文件名不能为空值),以及哪里出的错(readPreferences()的前部分)。
延迟捕获

异常发生时,不应立即捕获,而是应该考虑当前作用域是否有有能力处理这一异常的能力,如果没有,则应将该异常继续向上抛出,交由更上层的作用域来处理。
如何记录异常(写入日志)

在异常最开始发生的地方进行日志信息记录;
如果捕获到一个异常,但是这个异常是可以处理的。则无须记录异常;
捕获到一个未记录过的异常或外部系统异常时,应该记录异常的详细信息。
记录checked异常还是unChecked异常

如果一个异常是可以恢复的,可以被调用者正确处理的,使用checked异常;
如果一个异常是致命的,不可恢复的。或者调用者去捕获它没有任何益处,使用unChecked异常;
在使用unChecked异常时,必须在在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常;
受检异常尽可能转化为非受检异常。

在类继承的时候,方法覆盖时如何进行异常处理

如果父类的方法声明一个异常,则子类在重时声明的异常范围应该不小于 父类;
如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws;
如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不需要throws声明的。

java项目中异常处理情况的更多相关文章

  1. JAVA项目常用异常处理情况

    Java异常处理 网络整理 这里是异常的说明: 算术异常类:ArithmeticExecption 空指针异常类:NullPointerException 类型强制转换异常:ClassCastExce ...

  2. JAVA项目中常用的异常处理情况总结

    JAVA项目中常用的异常知识点总结 1. java.lang.nullpointerexception这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用 ...

  3. 对java异常的总结及java项目中的常用的异常处理情况

    文章涉及内容来源:黑马程序员自学整理的笔记,网上查阅资料,以及转载名为墨钺的博客大佬,附上博客转载地址:https://www.cnblogs.com/gothic-death/p/9946415.h ...

  4. JAVA项目中常用的异常知识点总结

    JAVA项目中常用的异常知识点总结 1. java.lang.nullpointerexception这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用 ...

  5. 在Java项目中整合Scala

    Scala是一个运行在Java JVM上的面向对象的语言.它支持函数编程,在语法上比Java更加灵活,同时通过Akka库,Scala支持强大的基于Actor的多线程编程.具有这些优势,使得我最近很想在 ...

  6. ckeditor编辑器在java项目中配置

    一.基本使用: 1.所需文件架包 A. Ckeditor基本文件包,比如:ckeditor_3.6.2.zip 下载地址:http://ckeditor.com/download 2.配置使用 A.将 ...

  7. Java项目中使用log记录日志的一些总结

    本文介绍了一下自己在Java项目中使用log的一些总结,从日志的作用.日志的选用.日志级别介绍.日志记录的一些最佳实践几个方面阐述. 日志的作用 主要作用包括: 1.出问题后定位当时问题 2.显示程序 ...

  8. 实战派 | Java项目中玩转Redis6.0客户端缓存!

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. 在前面的文章中,我们介绍了Redis6.0中的新特性客户端缓存client-side caching,通过tel ...

  9. eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错? java.lang.ClassNotFoundException: com.branchitech.app.startup.AppStartupContextListener java.lang.ClassN

    eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错?java. ...

随机推荐

  1. session会话示例

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...

  2. JavaScript+CSS+DIV实现下拉菜单示例

    <!DOCTYPE html> <html> <head> <title>下拉菜单示例</title> <script languag ...

  3. MySQL存储过程错误No data - zero rows fetched, selected, or processed

    原因:游标没有获取到任何内容! 解决方案 : 声明一个 continue handler declare continue handler for not found set V_NotFound = ...

  4. Linux:【解决】无法连接 MKS:套接字连接尝试次数太多正在放弃

    [解决]无法连接 MKS:套接字连接尝试次数太多正在放弃 操作: 我的电脑 -> 右键 -> 管理 -> 服务和应用程序 -> 服务: 开启下面的服务: ​ 服务启动成功后,重 ...

  5. 【Python】socket编程-3

    . SocketServer最简单的使用方法: () 创建一个Handler类,继承自BaseRequestHandler,重写其handle(),在该方法中完成对请求的处理. () 实例化一个Ser ...

  6. jQuery中AJAX同步如何实现?

    jax请求默认的都是异步的如果想同步 async设置为false就可以(默认是true) var html = $.ajax({  url: "some.php",  async: ...

  7. 微软Power BI 每月功能更新系列——7月Power BI 新功能学习

    Power BI Desktop 7月产品功能摘要 7月是Power BI Desktop团队的重要发布!但由于官方延迟更新,我们的讲述也就更晚了一点,也许大家觉得没有必要了,都8月了,谁还看7月的? ...

  8. 找出n个自然数(1,2,3,……,n)中取r个数的组合

    <?php /** * 对于$n和$r比较小, 可以用这种方法(当n=5, r=3时) */ function permutation1($n, $r) { for($i=1; $i<=$ ...

  9. JVM 自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优

    1. jstack:占用最多资源(CPU 内存)的Java代码 https://www.cnblogs.com/chengJAVA/p/5821218.html https://blog.csdn.n ...

  10. gcc/g++多版本切换 (ubuntu18.04)

    使用Ubuntu18.04已经有一段时间了,在使用过程中经常需要处理不同软件的编译工作,但是这时候就遇到这样一个问题,那就是不同软件,甚至是同一个软件的不同版本都会使用不同版本的gcc/g++来进行编 ...