Java异常(try/catch/finaly用法,throws和throw的区别)

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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,我们可以使用 `try...catch...finally` 结构来捕获和处理异常。`try` 块用于包含可能会出现异常的代码,`catch` 块用于捕获异常并进行相应的处理,`finally` 块用于在方法返回前执行一些必要的清理工作,例如释放资源等。 下面是一个使用 `try...catch...finally` 结构来读取文件内容的示例: ``` public static void main(String[] args) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("test.txt")); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException e) { System.out.println("文件不存在!"); } catch (IOException e) { System.out.println("读取文件失败!"); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { System.out.println("关闭文件失败!"); } } } } ``` 在上面的示例中,我们首先尝试打开名为 `test.txt` 的文件并读取其中的内容。在 `try` 块中,我们使用 `BufferedReader` 类和 `FileReader` 类来读取文件内容,并在 `while` 循环中逐行输出。如果在文件打开或读取的过程中出现了异常,那么就会进入相应的 `catch` 块进行处理。在 `finally` 块中,我们关闭了 `BufferedReader` 对象,确保文件被正确释放。 需要注意的是,在 `finally` 块中,我们需要判断 `BufferedReader` 对象是否为空,并在关闭之前使用一个嵌套的 `try...catch` 结构来捕获可能出现的异常。这是因为在关闭文件时也有可能出现异常,如果不对其进行处理就会导致文件没有正确关闭,从而引发其他问题。 总之,使用 `try...catch...finally` 结构可以帮助我们捕获和处理异常,并在必要的情况下进行一些清理工作,从而保证程序的健壮性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值