Java基础篇--异常机制

在之前的文章中,已经发布了常见的面试题,这里我了点时间整理了一下对应的解答,由于个人能力有限,不一定完全到位,如果有解答的不合理的地方还请指点,在此谢过。

本文主要描述的是java的异常机制,这个在实际面试中,问到的概率不算太大,但是在项目中,如何优雅的使用异常机制却是一个很大的学问。下面先看一个常见的面试题型。

public static void main(String[] args) {  
        System.out.println(test());  
    }  
  
    private static int test(){  
        int x= 1;  
        try {  
            return  ++x;  
        }catch (Exception ex){  
            return x++;  
        }finally {  
            ++x;  
        }  
    }  

这也算是面试中常见的一类面试题。上面的题目考察的知识点有++运算符,try catch finally 和return。在这里,先来看下上面的知识点后解答题目。

 

Java 的try catch finally过程:

实际在项目中,我们需要知道的是先执行try里面的内容,如果执行的过程中出现异常执行catch中的内容,最后不管是否执行过程中出现异常都会执行finally中的内容。如下,下面执行流程是:先执行(1)中的内容,最后执行(3)的内容,是否执行(2)的内容取决于(1)中的内容是否执行异常,如果(1)中执行的过程中出现问题就要执行(2)中的内容,如果没有就直接执行(3)的内容。

如果和return结合的话,我们也要执行finally中的内容之后才会return。换句话说,不管怎样,finally的内容都要执行。所以上面的打印内容是2。

请简单介绍JAVA的异常类?运行时异常和受检异常的区别是什么?Error和Exception的区别是什么?

我们通过一个简单的类图来描述一下,java的异常最大的父类是Throwable,其下两个子类是Error和Exception。Error代表的是错误,可能是系统内部环境错误,通过代码是无法解决的问题。这个时候只能通过停止虚拟机,其他别无选择。而exception是代码在设计上的缺陷导致,这个有可能是程序在设计时没有考虑到的场景导致,这个时候不需要停止虚拟机,更多的是希望对异常捕获之后进行异常处理。所以error是比exception更为严重的错误。Exception又可以分为两大类:运行时异常和受检异常;受检异常一般是指在程序中需要捕获的,这种异常一般都需要我们在catch中进行处理,而运行时异常是jvm自己管理的,我们一般不需要在代码中处理,如果发生异常的时候,代码会一直往外抛,直到最上层的代码

 

举例说说你平时碰到的Error和Exception?

平时碰到的Error类:

AssertionError:断言错误

IllegalAccessError非法权限错误

InternalErrorjava虚拟机内部错误

NoClassDefFoundError:java虚拟机在类初始化时找不到类的定义错误

NoSuchMethodError:类不存在该方法错误

OutOfMemoryError:分配内存时,内存溢出错误

StackOverflowError:栈溢出错误

Exception类:

运行时异常(RuntimeException):

NullPointerException:空指针异常

IndexOutOfBoundsException:下标越界异常

ClassCastException:类强制转换异常

NumberFormatException:数字格式化异常

IllegalArgumentException:参数错误异常

受检异常(checkedException):

SQLException:SQL异常

IOException:IO操作异常,这个是一个很大的异常类,其子类常见的有FIleNotFoundException,EOFException,SocketException;

InterruptedException:中断异常

NoClassDefFoundError 和ClassNotFoundException 的区别是什么?

我们至少可以根据后缀判断出Noclassdeffouderror 是error级别的,它是虚拟机抛出的,而classnotfoundexception是exception级别的,它是由代码中产出。Noclassdefounderror 一般是由于java类在编译完成之后,迁移过程中,class文件的丢死导致,jvm在加载类的时候抛出的错误。而classnotfoundexcption一般是动态加载类的时候,没有在类的路径下找到该类抛出的异常

 

Throw和Throws的区别是什么?

当我们在代码中希望明确抛出一个异常的时候,我们使用Throw关键字将异常抛出到函数体上,对外抛出。当我们需要在函数体上对外抛出异常的时候,我们使用throws关键字将函数的各种异常对调用方抛出。我们看一段简单的代码就能明白throw和throws的区别了。

private static int test() throws Exception {//将函数体的异常抛出

        int x= 1;

        try {

            return ++x;

        }catch (NullPointerException ex){

           throw  new Exception("test");//将异常抛至函数体

        }finally {

            ++x;

        }

  }

final、finally、finalize的区别是什么?

这几个词只是长得有点相同,其实它们在java中没有任何关系。

Final是固定的意思,它的常见用法是用来修饰变量,类,方法,当我们修饰变量的时候final修饰的是常量,当修饰方法的时候,表示方法不能被覆盖,当修饰类的时候,表示类不能继承。当然还有一种是修饰方法内的变量,这种在λ表达式的时候经常会被使用到,这个就是表示传过来的值是不允许改变的。

Finally是最终的意思,这个是在java异常机制中,表示都要执行的意思,这个在上面的内容中已经提到了,这里不多说明。

finalize是java的一个方法,它不是关键字,它是jvm垃圾回收的时候使用。我们知道finalize是object的一个方法,任何一个对象都有该方法,jvm在垃圾回收的时候,回收线程会先判断对象是否不可达(GCRoot不能连接),如果不可达就代表可以回收,这个时候判断该对象是否覆盖了finalize方法,如果没有覆盖,直接回收;如果有覆盖,就将该对象放置在一个F-Queue队列中,由优先级低的线程执行,如果执行完成之后,再次判断该对象是否不可达,如果不可达就直接回收,如果可达的话,就是我们常说的对象逃逸。这是finalize函数的设计初衷,一般我们在实际项目中很少会用到这个方法,毕竟垃圾回收我们希望虚拟机自己管理就好了。

 

一般在实际项目中,有哪些处理异常的方法,说说你的理解?

  1. 异常的分类处理,自定义异常的使用。项目中异常的分类很有必要,不同的异常对应着不同的处理方式,有些异常可以忽视的话,就不建议往外抛出。
  2. 异常类的创建和统一规范打印,项目中规范好异常的打印方式,可以有效的判断出是哪个服务哪个类出问题,并且又能保证关键信息不被泄露。
  3. 如果是非常重要的方法不允许抛出异常的话,可以在函数的开始直接使用try catch 进行捕获,这个是有效防止运行时异常导致整个程序后续执行出现问题。
  4. 异常尽量最小化,和前段界面交互的话,尽量将异常描述的用户能懂,不建议直接将异常内容抛出,防止信息泄露
  5. 可以使用函数式接口将异常的处理进行封装,防止一段代码中异常太多,导致程序的可读性太差。看下面一个例子哈:
//test方法

public void test(){

        try {

            //do sth

        }catch (ExceptionA ex){//不同的exception 异常

            

        }

        try {

            //do sth

        }catch (ExceptionB ex){

            

        }

        //....

        try {

            try {

                

            }catch (ExceptionC ex){

                

            }

        }catch (ExceptionD ex){



        }

        try {

            //do sth

        }catch (Exception ex){



        }

        

}

使用函数式接口定义异常处理方法:

public static void hand(ExConWithNoReturn consumer){

        try {

            consumer.hand();

        }catch (Exception ex){

            log.error("hand ex:",ex);

        }

}

切换之后的方法就变成了:

public void test(){

        ExceptionHandler.hand(()->{

            //do sth

        });

        ExceptionHandler.hand(()->{

            //do sth other

        });

        ExceptionHandler.hand(()->{

            //do sth other

        });

}

这样代码看上去可读性会高点。

 

Java异常处理的问题基本就这么多,本文到这里就基本结束了,如果你觉得对你的学习和面试有些帮助,帮忙点个赞或者转发一下哈,谢谢。

 

想要了解更多java内容(包含大厂面试题和题解)可以关注公众号,也可以在公众号留言,帮忙内推阿里、腾讯等互联网大厂哈

                                   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值