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异常(代码片段