本文为原创,转载请注明
作者:cha1R(tanjiayqq)
Java里异常分两种,一种是检查(checked)的,一种是非检查(unchecked)的。
非检查以RuntimeException作为典型代表,它有一个特点就是我们可以不用捕捉它,如果没有捕捉它,它会一直往上抛直到main()方法处理,从而退出整个程序。注意如果是多线程的话,它并不会在main()方法终止程序,它会一直往上抛直到run()方法,而run()方法没有捕捉它的话会终止线程。
作为业务异常,是要反馈给用户的,所以我们不希望发生任何终止线程或者终止程序的代码。所以定义业务异常,我们一般使用检查的(checked)异常,定义一个异常非常简单,只需要写一个简单的类继承Exception即可。
public class InvalidAccount extends Exception{ private static final long serialVersionUID = 1L; public InvalidAccount(){ super("无效的账户"); } public InvalidAccount(String msg){ super(msg); } }
那么我们一般什么时候需要设计业务异常呢?从我的经验来看,一般是设计业务接口的时候需要考虑这个接口会引发的业务异常。
假设设计一个登陆业务接口:
/** * 登录 * @param username 用户名 * @param password 密码 * @return 是否登录成功*/ boolean login(String username,String password);
显然这个接口没有抛出异常,那么我们在还没实现接口的情况下,该如何考虑这个接口会发生什么样的异常?
其实我们很难全面地预测到它会发生一些什么,但是我们只需要考虑业务异常,业务异常是什么?即应用异常(如 权限不够等),这类异常需要通过前台反馈给用户,友好提示用户当前操作异常。
最大的特点就是,这个异常一定是由于当前接口调用不当(即用户操作不当,因为它接收的是用户输入的数据)造成的,那么最直接的思路就是从传入参数入手:
从登陆接口来看,传入的是用户名和密码,那么我们可以抛出一个“无效的用户”或者抛出“无效的用户名”和“无效的密码” 异常,其他的都不用抛出,因为它并不是由调用者引发的,在方法内部处理完就行。
再来看看一个我们一个项目的业务接口,评论微博:
/** * 评论 * @param userId 被评论的用户的ID * @param weiboId 被评论的微博的ID * @param content 评论内容 * @return */ boolean comment(String userId,String weiboId,String content);
定义这个方法的异常还算比较简单,从参数入手
userId:用户不存在异常
weiboId:微博不存在异常
content:内容包含敏感词汇异常,内容超出字数限制异常。 或直接用一个 内容不合法异常
这些都是可以抛出的异常。
但是有时候一条微博可能被设置为 “不可评论”,那么我们是不是要再跑出一个“不可评论异常”?这个完全不必抛出,因为我们抛出业务异常是用来反馈给用户看,从而让用户做出相应处理,但是这种不可改变的情况完全没必要交给用户决定如何处理,只需要在方法内部抛出RuntimeException,UI层统一捕获,提示一下即可。
最后介绍一个学习网站,比较适合初学者,视频略多:Here