Java异常(try/catch/finaly用法,throws和throw的区别)
有特殊情况finally块是不会执行的①System.exit(),表示中止当前虚拟机,虚拟机都被中止了,finally代码块自然不会执行,②守护(daemon)线程被中止时,Java线程分为两类,守护线程和非守护线程。Throwable: 是最顶层的父类,有两个重要的子类:Exception(异常)和 Error(错误),异常是指程序本身可以处理的异常,异常又分为编译时异常和运行时异常。
Java异常结构图
Throwable: 是最顶层的父类,有两个重要的子类:Exception(异常)和 Error(错误),异常是指程序本身可以处理的异常,异常又分为编译时异常和运行时异常。
异常(exception)
-
编译时异常:是指在程序运行之前代码出现的错误导致程序无法正常运行,例如代码下面出现红线提示,需要我们抛出(throws)异常或者try catch异常捕获。
-
运行时异常(RuntimeException):指我们在开发中测试功能时程序终止,控制台出现的异常,常见的运行时异常有 NullPointerException(空指针异常)、 IndexOutOfBoundsException(下标越界异常), ClassCastException(类转换异常), ArrayStoreException(数据存储异常,操作数组时类型不一致) , IO操作的BufferOverflowException异常
错误(error):error类体系描述了Java运行系统中的内部错误以及资源耗尽的场景,例如堆内存溢出,栈溢出等
关于try-catch-finally
为了更好的理解try-catch-finally,先看下面几段代码
//代码片段一
public static String GetStr(){
try{
Console.WriteLine("走到:try");
return "这里是try返回值";
}catch (Exception e){
Console.WriteLine("走到:catch");
return "这里是catch返回值";
}finally{
Console.WriteLine("走到:finally");
}
return "这里是方法底部返回值";
}
//输出结果
走到:try
走到:finally
这里是try返回值
//代码片段二
public static string GetStr()
{
try
{
int value = 0;
Console.WriteLine("走到:try");
var i = 1 / value;//这里会出错 0不能被整除
return "这里是try返回值";
}
catch (Exception e)
{
Console.WriteLine("走到:catch");
return "这里是catch返回值";
}
finally
{
Console.WriteLine("走到:finally");
}
return "这里是方法底部返回值";
}
//输出结果
走到:try
走到:catch
走到:finally
这里是catch返回值
//代码片段三
public static string GetStr()
{
string str = "";
try
{
str = "修改成了a";
Console.WriteLine("走到:try");
// return "这里是try返回值";
return str;
}
catch (Exception e)
{
Console.WriteLine("走到:catch");
return "这里是catch返回值";
}
finally
{
str = "修改成了b";
Console.WriteLine("走到:finally");
}
return "这里是方法底部返回值";
}
//输出结果
走到:try
走到:finally
修改成了a
总结:
-
不管try中是否有异常,finally方法块都会被执行,如果try{}中有异常,则异常下面代码不执行
-
就算try和catch方法都有return,finally都会执行
-
只要try或者catch 有return返回,try catch 之外的return都无效;
-
虽然finally方法会被执行但是返回结果不会被改变,也就是如果finally是在return之后执行的那么他会把返回结果先保存起来,然后不管finally代码执行了什么,都不会影响到返回结果,等finally执行完成在返回结果。但是如果finally中有return语句,执行的是finally中的return语句,如果进行值操作将会覆盖try中的值
问题:finally真的就一定会执行吗?
有特殊情况finally块是不会执行的①System.exit(),表示中止当前虚拟机,虚拟机都被中止了,finally代码块自然不会执行,②守护(daemon)线程被中止时,Java线程分为两类,守护线程和非守护线程。当所有的非守护线程中止时,不论存不存在守护线程,虚拟机都会kill掉守护线程从而中止程序。 虚拟机中,执行main方法的线程就是一个非守护线程,垃圾回收则是另一个守护线程,main执行完,程序就中止了,而不管垃圾回收线程是否中止。 所以,如果守护线程中存在finally代码块,那么当所有的非守护线程中止时,守护线程被kill掉,其finally代码块是不会执行的。
注意:try、catch,finally组合写法,不能写多个try,但是可以写多个catch,可以try/catch或者try/finally组合。
public class Test {
public static void main(String[] args) {
try{
int y=10/0;
}
catch(ArithmeticException ae){
System.out.println("Arithmetic Exception");
}catch(Exception e){
System.out.println("Exception");
}
System.out.println("finished");
}
}
输出结果为:
Arithmetic Exception
finished
如果将上面的catch(ArithmeticException ae) 和 catch(Exception e) 的位置交换,程序会报错,因为Exception e 是 ArithmeticException ae 的父类。当父类在子类前面,抛出的异常已经被父类处理了,后面的子类就不能接收异常。
总结:在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面
throws和throw的区别?
throws是在我们处理非运行异常时要么使用throws抛出或者try/catch捕获异常,throw是我们在进行try/catch时将异常抛出,是在方法内部
异常到底什么时候抛出什么时候捕获?
说一下个人理解,当我们在做web开发时,一般都是基于三层架构去开发,即controller(控制层),service(业务逻辑层),dao(持久层),假如我们在控制层去抛出了异常,这其实对用户来说是很不友好的,因为controller和用户页面对接,用户也看不懂我们程序抛出的异常,所以需要在controller层进行全局异常处理,封装一些错误码,友好的提示用户,接着说一下service层,业务层需要处理业务逻辑,当然这一层不需要考虑参数是否为空,需要考虑的仅仅是从dao查询相关的异常,比如ConnectionExcepion、SQLException、BadSQLGrammerException等异常,这些异常我通常会去捕获,因为这些异常涉及到业务逻辑是否能正常执行,做法是try...catch...捕获所有Exception,然后在catch中用logger.error("message, e = {}", e.getMessage())记录日志信息,用于到时候定位error代码位置,然后根据实际业务情况,看这个异常捕获后是否需要用一个异常封装一下信息抛给控制层,然后由控制层统一处理也好或者直接返回给用户)。
spring MVC全局异常处理
一、创建自定义异常类CustomException
public class CustomException extends Exception{//如果继承RuntimeException就是处理运行时异常
private String message;
public CustomException(String message){
this.message=message;
}
public String getMessage(){
return message;
}
}
二、创建自定义异常处理器CustomExceptionResolver
public class CustomExceptionResolver implements HandlerExceptionResolver{
ModelAndView mav=new ModelAndView();
@Override
public ModelAndView resolveException(HttpServletRequest re,HttpServletResponse rp,Object o,Exception e){
if(e instanceof CustomException){
//如果这个异常类型是我们自定义异常类型,加入到自定义异常类,通过getMessage拿到异常信息
mav.setAndView("error");
mav.addObject("message",e.getMessage());
}else{
mav.setAndView("error");
mav.addObject("message",系统错误!);
}
}
}
三、在springMVC.xml中配置异常处理器,将它注入容器
<bean id="CustomExceptionResolver" class="com.demo.resolver.CustomExceptionResolver"></bean>
四、测试
public class testController {
@RequestMapping(value="/test")
public String test(){
try{
int i=10/0;
}catch(Exception e){
throw new CustomException("整数初0啦...")
}
return "target";//跳转页面
}
}
以上就是我个人对Java异常的总结,如果对你有帮助希望点点赞,谢谢啦........
更多推荐
所有评论(0)