Java中的异常

Posted mvcq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的异常相关的知识,希望对你有一定的参考价值。

异常是程序运行过程过程出现的错误,在Java中用类来描述,用对象来表示具体的异常。 Java将其区分为Error与Exception,Error是程序无法处理的错误,Exception是程序可以处理的错误。 异常处理是为了程序的健壮性。

Thorwable类是所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常。 其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常, 这两种异常有很大的区别,也称之为非检测异常(Unchecked Exception)和检测异常(Checked Exception)

下面来通过代码直观地看一下这两者的差别:

检查异常:

技术分享图片

如上图所示,如果不对红线所存在的异常进行处理,该代码是无法通过编译的。必须对其进行throws或者try-catch:

技术分享图片

如上图所示,对两个异常进行了try-catch处理,代码可以正常编译。那么这样的异常(FileNotFoundException和IOException)就叫作检查异常,也叫作非运行时异常,意思是在编译前就应该对该异常进行处理,否则无法通过编译。

非检查异常:

技术分享图片

如上图所示,出现了ArrayIndexOutOfBoundException,这个异常是编译成功,运行时出现的异常,顾名思义,该异常意思是数组角标越界了,由于该异常是在运行时出现的异常,所以此类异常也叫作运行时异常,或非检查异常。类似的异常还有NullPointerException等。

自定义异常:

上面出现的几种异常不管是什么类型,都是Throwable的间接子类,都已经封装完毕,我们直接使用就行,但有时候我们系统根据需求会出现各种各样的异常,这时候就要自定义异常对象了。自定义异常,也是将异常进行封装,说白了就是用一个自定义的类对异常信息进行封装,该类继承Exception,只需要复写父类的构造方法即可,通过super将信息传入到参数。先来看看父类的构造是如何实现的:

Exception:

技术分享图片

 

Throwable:

技术分享图片

技术分享图片

这就很明显了,我们在自定义异常类时,在构造方法中用super调用了该类的父类Exception中的构造方法,并将参数传入,在Exception中用super调用父类Throwable中的构造方法,并将参数传入,并将该实参值赋值给该类的detailMessage属性,在getMessage()方法中获取该值,所以也就有了"myException.getMessage()"(下文会提到)了,可以看得出来这个方法其实是调用的Throwable类中的方法。

 

假设当前有个需求:对于用户输入的用户名进行检测,如果用户名不是“张三”,则抛出我们自定义的异常对象myException,并打印异常信息。

自定义的异常类:

 

1 public class MyException extends Exception{
2 
3     private static final long serialVersionUID = 1041819209403514525L;
4     
5     public MyException(String message) {
6         super(message);
7     }
8 }

 

controller层:

1 public class UserController {
2     private UserService userService = new UserService();
3     
4     public User queryUser(String name,String password) throws MyException {
5         return userService.queryUser(name,password);
6     }
7 }

service层:

1 public class UserService {
2     private UserDao userDao = new UserDao();
3     public User queryUser(String name, String password) throws MyException {
4         return userDao.queryUser(name,password);
5     }
6 }

dao层:

 1 public class UserDao {
 2 
 3     public User queryUser(String name, String password) throws MyException {
 4         if (!"张三".equals(name)) {
 5             throw new MyException("输入的密码或者用户名错误");
 6         }
 7 
 8         User user = new User();
 9         user.setUsername(name);
10         user.setPassword(password);
11 
12         return user;
13     }
14 }

测试:

 1 public class Test {
 2 
 3     public static void main(String[] args) {
 4         UserController userController = new UserController();
 5         try {
 6             User user = userController.queryUser("张大三", "111");
 7             System.out.println(user);
 8         } catch (MyException myException) {
 9             System.out.println(myException.getMessage());
10         }
11 
12     }
13 }

如上图所示:在测试类中调用controller中的方法queryUser(String name,String password)来查询用户,该方法内部调用的是service层的queryUser(String name,String password)方法,service中的该方法内部调用的是dao层的queryUser(String name,String password)方法,在dao层的该方法内部,对方法参数进行了判断,如果参数满足某条件就出现异常,将该异常抛出,并在方法声明部分进行throws声明,告知调用该方法的对象,该方法可能存在异常,你要调用,就要对其处理,至于处理的方法取决于调用者,要么直接在方法声明部分throws抛出,交给更上一层,要么进行try-catch,那么当前的调用者是谁呢,调用dao层该方法的是service层,那么service层中只是进行了throws,将异常继续向上抛了,同理,调用service的是controller,controller同样也是进行了throws,那么在测试类Test中调用controller层的方法,进行了try-catch处理,对可能出现异常的代码进行try,如果监听到的异常和catch捕获的异常对象对应,那么就对其处理,此处处理只是简单打印异常信息:

技术分享图片

 

以上是关于Java中的异常的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.NullPointerException: Attempt to invoke virtual method ‘int android.database.sqlite异常(代码片段

片段中的Android致命异常

异常和TCP通讯

片段中的getView()导致抛出异常,不确定原因

java 反射代码片段

片段中的空指针异常