【Java基础专题】7. 异常五连击,按照提问逐一回答

本问题对应的项目链接:高频题回答模版训练

1、说一说你对异常的理解?(指导:就是回答异常有啥用之类的)

2、异常有哪些种类,可以举几个例子吗?(指导:先回答分类,之后举几个自己经常看到的例子)

3、throw 和 throws 有啥区别?直接 try catch 不好吗,为啥还要抛呢?

4、try catch会影响性能吗?为什么抛出异常的时候会影响性能?

5、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?(指导:finally是易错的地方,可以说一说)

请在下面逐一打卡回答

共以下 14 个回答

  • 八点上线 永久会员 2024年12月13日 上午1:23

    1.异常就是程序运行时可能出现的错误,对这部分代码统一规范处理
    2.Throwable是所有异常的父类,有两个子类,error和exception,error是严重的系统级错误,比如内存溢出,excetion是程序可以处理的异常,分为runtimeexception和checkedexception,runtimeexception无需显式处理,比如指针为空或者数组越界,checkedexception必须显示处理才能通过编译,比如IO异常或者文件未找到
    3.throw作为语句抛出异常,throws放在方法的声明可能抛出的异常,要求调用者用try catch处理,抛的好处是一个函数调用的其它方法可能有相同的异常,抛给调用者统一处理,另外当前方法无法处理的异常可以抛给调用者处理
    4.没有发生异常,几乎不会影响性能,发生异常以后,创建异常对象要收集调用栈信息,逐层回溯整个调用链路,另外还要找到catch,影响性能
    5.会

    0 赞同 0 条回复
  • Silence 永久会员 2023年10月22日 下午10:57

    1 首先我对异常的理解的话,就是异常它可以提高程序的健壮性。如果说没有异常这种机制的话,我们在程序中写了一段错误的逻辑,就比如说出现了除零这个错误的写法。程序在执行到这里之后,它就只能中断退出。有了异常这个机制之后,你可以用语句把它不过然后根据你自己的逻辑来决定这个程序接下来怎么走。他就不是必须要停下来。其次,我认为异常它能够带给我们一个好的提醒能够让我们写代码中有一个好的交互性。就比如说我们在写错了一些逻辑之后,如果说没有这个异常的机制,我们就压根儿不知道错在哪里。不知道我们的错误是什么,引入了这个异常的机制之后,我们在捕获一场之后可以将异常信息进行输出。就能引导我们快速的定位到我们代码中的逻辑错误。

    2 异常的话,它就是exception,它继承于throwable这个类。然后再细分的话,可以分为检查异常和非检查异常。检查异常的话也叫做普通异常,遇到这种异常就必须要用来try,catch,finally这种语句,来把它进行一个代码的处理。如果说不进行这样的处理的话,编译都不能通过。就比如说SQL exception或者说是io exception。另一种异常的话叫做非检查异常,就是你可以在代码中不管它。通常来说这种异常的话,它的影响会稍微小一些,就比如说这种算数的数学除零异常。或者说是宿主越界一场。

    3 throws位于方法头。他主要是为了向外申明这个方法他有可能会出现哪一些异常。而throw是它是位于这个方法的内部,它的作用就是用于抛出某个异常。当你用这个关键词来声明异常的时候,调用它的方法也必须要对这个异常进行一定的代码处理。否则变异不会通过。我们用是声明异常并且抛出异常的原因,就是为了让调用这个方法的人能够察觉这个异常。否则这个异常他有可能不被我们察觉,这样的话就可能导致程序是有错误的,但是我们并不知道他错在哪里。

    4 使用Try catch会对性能有影响。如果说没有出现异常的话,其实是没有影响的。但是说如果出现了异常的话,主要就有catch语句中的代码来决定这个异常的影响是大还是小,如果说开启语句中什么都不做的话,其实也没有什么性能的影响,但是如果说你需要把错误的信息打印到日志上的话,那么对性能有极大的影响,因为他会去记录一个错误的,这样的一个调用的栈信息。通常有可能会嵌套很多很多的层对性能的影响还是比较大的。

    5 仍然会执行finally中的代码,因为不管有没有异常,finally他都是会执行的,然后的话在return之前,他会把要return的结果保存在一个临时变量中。把finally中的代码执行完之后,再把这个临时变量进行返回。需要注意的是,如果说在finally中有一个return语句的话,那么它返回的就不是临时变量中的值,而是finally中的结果。

    0 赞同 0 条回复
  • CrazyJavaBoy 永久会员 2023年9月15日 下午5:22

    1、异常的理解:
    异常是在程序执行过程中发生的不正常或意外的事件,它们可以干扰程序的正常执行流程。异常用于处理错误情况和异常情况,使程序能够以一种有序和可控的方式应对问题,而不是崩溃或产生未定义的行为。异常处理的目标是在错误发生时提供有关问题的信息,并允许程序采取适当的措施来处理或恢复,从而保护系统的稳定性和数据的完整性。
    2、异常的种类和例子:
    异常可以分为两大类:受检查异常(Checked Exception)和非受检查异常(Unchecked Exception)。
    受检查异常:通常是程序无法控制的外部因素引起的异常,需要显式地在代码中进行处理,例如 IOException、SQLException。
    非受检查异常:通常是程序中的错误引起的异常,无需显式处理,但最好也进行处理以提高程序的健壮性,例如 NullPointerException、ArrayIndexOutOfBoundsException。
    3、throw 和 throws 的区别:
    throw:用于在代码块中抛出一个异常对象。通常在方法内部使用,用于手动触发异常。例如,throw new Exception(“Something went wrong”);。
    4、throws:用于方法声明中,指定该方法可能抛出的异常类型。可以抛出多种异常,这是一种声明,告诉调用者可能需要处理哪些异常。例如,public void myMethod() throws IOException。
    5、直接使用 try-catch 可以捕获和处理异常,但它只适用于方法内部的异常处理。throws 主要用于将异常传播给方法的调用者,让调用者决定如何处理异常。这样可以在程序的不同层次中进行异常处理,并提供更灵活的错误处理策略。
    6、try-catch 对性能的影响:
    使用 try-catch 块来捕获和处理异常通常不会对程序的性能产生显著影响。异常处理仅在异常被抛出并捕获时才会涉及性能开销。因此,只有在异常实际发生时才会有性能开销,而不是在正常情况下。
    7、try-catch-finally 中,如果 catch 中使用了 return,finally 仍然会执行:
    不管 catch 中是否有 return,finally 块中的代码都会执行。finally 块通常用于执行清理操作,例如释放资源(如关闭文件或数据库连接)或确保某些代码一定会执行,无论是否发生异常。如果 catch 中有 return 语句,finally 仍然会在 catch 执行后执行,并且 finally 中的 return 会覆盖 catch 中的 return。
    这就是为什么要小心使用在 finally 块中使用 return,因为它可能会改变方法的返回值,这可能不是你期望的行为。通常在 finally 块中不要使用 return,而是在 catch 中捕获异常后返回需要的值。

    0 赞同 0 条回复
  • LilyBoy 永久会员 2023年9月6日 上午10:50

    3、throw 和 throws 有啥区别?直接 try catch 不好吗,为啥还要抛呢?
    方法声明时抛出异常;
    方法内执行抛出异常;
    4、try catch会影响性能吗?为什么抛出异常的时候会影响性能?
    a.没有抛出异常不影响
    b.有异常处理会
    if条件判断时
    for循环

    0 赞同 0 条回复
  • 中国用户 永久会员 2023年6月26日 下午5:54

    1.异常就是程序执行发生的错误异常情况;
    2.异常分为已检查异常和未检查异常,ClassNotFoundException,找不到class类;未检查异常即Runtime Exception,空指针异常,类型转换异常那五个;
    3.throw在方法体中,throws在方法声明后面,使用try-catch不能将异常传给调用者来处理;
    4.会,消耗资源和时间;
    5.如果 catch 中 return 了,finally 还会执行,覆盖catch里面的return。

    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年6月20日 下午3:06

    1.我理解的异常就是出错了呗,不管是空指针异常还是Io异常,都属于是出错的一种;
    2.异常分为checked exception:必须处理的异常,不然编译不通过。除了runtimeException及其子类以外的所有异常都是受检异常,比方说filenotfound、pathnotfound、io异常等
    和unchecked exception:指runtimeException及其子类,常见的非受检异常有:空指针异常、指针越界异常等等
    3.throw 是用在方法或者代码块里面用于主动抛出一个异常对象;throws关键字用在方法声明中指定方法可能抛出的异常类型。用需求方面来讲,有时候直接抛出异常,以方便对异常进行统一处理,
    4.如果没有异常发生不会影响性能,如果有异常发生就会影响性能;
    因为抛出异常的时候,系统构建异常对象、查找相应异常处理器等,会造成额外开销
    5.会,在catch或者try代码块执行return之前就会去执行finally代码块,建议finally代码块里面不要有return语句。

    0 赞同 0 条回复
  • 。 永久会员 2023年6月18日 下午8:47

    1.当程序不能正常运行时,直接退出会影响用户体验,可以通过返回遇到的障碍给调用者,让调用者解决,保证程序健壮性。
    2.异常包括运行时异常和错误,比如在编译时可以发现的语法错误,NullPointerException, StackOverFlowException.
    3.throw在方法体内,只能抛出单个异常,throws在方法声明后,throws可以抛出多个异常 。一些异常自己可能处理不了,只能交给调用者解决。
    4.try catch在没有异常时不会影响性能,有异常时需要做获取整条调用栈的信息,释放占有的资源,寻找合适的异常处理器,抛出异常等操作,影响整体的性能。
    5.会在catch的return前保存返回值,执行finally的代码后返回保存的返回值。

    0 赞同 0 条回复
  • Gary 永久会员 2023年6月2日 上午9:59

    1.异常指的是程序可以处理的exception,应该尽可能地捕获,捕获后尽可能地恢复,而不应该随意终止。与异常相近的概念是error,error指的是程序无法处理的错误,一般是内存溢出、系统崩溃、虚拟机错误、方法调用栈溢出等JVM相关的问题,遇到的话只能让程序终止。对于异常的处理,通常采用抛出异常或捕获异常的方式来处理,抛出异常指抛出一个Throwable对象或者是Throwable的子类对象,交由运行时系统处理;捕获异常指寻找合适的异常处理器来处理异常,否则终止运行。在捕获异常时,应该注意保留原始的信息,可以打印在日志里面保存起来,以便于定位问题并进行调试。
    在程序运行的过程中,我们需要对异常进行统一处理,在Controller层,需要对各种自定义的业务异常进行统一拦截,返回给前端;在Service层,可以统一拦截数据库操作相关的异常,包装成自定义的业务异常向上抛;在全局层面,可以对其它未捕获的Throwable对象跟它的子类对象统一拦截,返回给前端。
    2.异常分为运行时异常RuntimeException和非运行时异常。非运行时异常,在编译阶段就能知道,而运行时异常,可以用程序来避免或者做一些补救措施,例如:先判断对象是否为空,再调用这个对象的方法,来避免空指针异常NullPointerException;常见的异常还有类型强制转换异常ClassCastException,传递非法参数异常IllegalArgumentException、下标越界异常IndexOutOfBoundsException、数字格式异常NumberFormatException
    3.throw是用在方法体内,主动抛出一个异常对象,而且只能抛一个,一般用在try/catch里面。
    throws用在方法声明后面,用来指定抛出一个或多个异常类型,让捕获者可以捕获或者处理这些异常。
    throw表示一定发生了某个异常,而throws表示可能会发生这些异常。
    有些异常不适合在当前方法中处理,而要抛给上层,让上层的调用者决定如何处理。例如:一个方法要读取一个文件,此时找不到这个文件,就抛出一个IOException,让上层调用者决定如何处理,例如重新选择一个文件或者提示用户错误信息,如果直接捕获了,可能无法通知调用者发生了什么问题,也无法让调用者有机会处理问题。
    4.如果try catch没有抛出异常,那么对性能几乎没影响,只是多了一些判断。
    但是如果try catch抛出了异常,对性能影响就很大,因为抛出异常需要做很多事情,例如:
    当一个异常被抛出,首先要创建一个异常对象,包含异常的类型、消息、栈信息等属性,需要占用内存空间;其次,要携带当前线程的调用栈信息,需要遍历当前线程的所有栈帧,并且将它们转换成字符串形式。然后JVM会寻找一个合适的异常处理器,来处理这个异常,需要匹配异常的类型和范围,从最近的栈帧开始向上查找,直到找到一个匹配的catch块或者到达栈顶。如果当前方法还有一些未完成的操作或者没有释放的资源,例如打开的文件流、持有的锁等,需要对这些资源进行清理,避免内存泄漏或者死锁。
    5.finally的代码,无论前面是否有catch异常,都会执行的。如果catch和finally都有return,那么finally里面的return,会将catch的return覆盖掉。

    1 赞同 0 条回复
  • upward ᯤ⁶⁰ᴳ 永久会员 2023年6月2日 上午9:10

    1:如果能接收到异常并且进行处理就可以避免程序中断
    种类:ERROR和Exception:OOM 数组越界,类型不匹配 空指针
    例子:堆内存空间不足时创建大对象超过年轻代空间和老年代剩余空间,fullGC解决不了就会OOM;剩下。。。
    3:throw用在函数内部 throws用在函数头,throrw非RuntimeException就要在函数头上加throws。有些错误是当前方法不能解决的,需要抛出去给上层用户,比如0除错误,有些错误可以堆积起来一起给上层解决,节省资源
    4 try…catch本身不会影响系统性能,但是我们出现异常时系统处理我们的异常会带来系统开销。
    5 会执行,比如catch中return “a”;那么先生成”a”对象储存,然后执行finally,最后再return储存值

    0 赞同 0 条回复
  • 小鱼 永久会员 2023年5月30日 下午8:37

    1,异常是程序执行中出现的一些意外,就需要我们来解决。
    根父类是throwable,包括 Error 和 Exception,一般我们要解决的异常是编译是异常,运行时异常应该避免,error是jvm死机了,严重错误。例子:空指针异常(NullPointerException),角标越界(ArrayIndexOutOfBoundsException),类型不匹配异常(InputMismatchException)等
    3.throw是我们自己抛出来异常,需要去解决,或者往上抛,throws则就是不解决往上抛的那个,抛给方法的调用者,当然一般建议别抛到main函数,在main之前try catch。 直接抛出去可能要抛出去多次,每次都try catch影响性能吧,可以交给一个最上面的调用者一块儿解决。
    4,出现异常的时候影响,不出就不影响
    5,执行,程序先把catch的return暂时存放,然后finally执行后才返回,但是当程序进入 try 块之前就出现异常时,就结束,不会执行 finally 块中的代码。

    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年5月28日 下午5:14

    1、异常是指我们的程序在执行的过程中出现的一些错误,如果程序在执行过程中发生错误,我们希望程序能够根据我们的异常寻找一个出口,告知到我们的客户或者程序员,能够使程序正常的退出。
    2、异常分为error和exception异常,他们都是Throwable的子类。error异常主要是虚拟机异常,比如系统崩溃、虚拟机错误、内存不足、堆栈溢出等问题,该异常无法通过修改程序代码来解决。exception是程序的问题,又被分为运行时异常和编译时异常。
    3、throw主要是在方法体内部抛出一个异常,由方法体内部进行处理,是一个抛出的动作,抛出的是一个异常实例。throws是在方法声明部分的后面使用,向上抛出异常,将抛出的异常交给方法调用者来解决。对于异常,我们不一定是只会在这一层会产生这个异常,如果我们在每个产生该异常的地方都使用trycatch抛出,那么相同的异常我们可能需要在同一个程序中抛出多次,影响程序的可读性,并且会带来多次处理异常的开销。
    4、try…catch本身不会影响系统性能,但是我们出现异常时系统处理我们的异常会带来系统开销。
    5、会的,程序会将我们的return值存储起来,然后执行finally中的内容,对于基本数据类型,如果finally中修改了该数据不会对返回造成影响,如果是引用数据类型,会返回finally中修改后的该引用的对象。

    0 赞同 0 条回复
  • 小肸 永久会员 2023年5月27日 下午9:05

    人都会发错,更何况程序,如果程序出错,我们希望可以把之前程序完成的工作保存下来然后正常退出,而不是丢失已经完成的结果。这就是异常需要完成的事情。异常分为Error和Exception。Error就是错误,这种错误会导致程序无法运行,比如堆溢出、栈溢出等。想IO异常、套接字异常等这些都是受检查型异常,这些异常在我们编写程序时就可以知道可能会发生的异常,当你打开一个文件时,就知道这个文件可能不存在,所以需要throw来抛出一个文件不存在异常,必须使用catch或者throws处理这个受检查型异常。try包住可能会抛出文件不存在的异常的代码块,然后catch捕获文件不存在异常,在catch的代码块写入处理逻辑。而数组越界异常、空指针异常这些都是程序运行时,才可能会发生的异常,大都不可能知道在哪些地方可以具体捕获,所以无法使用try包住,也无法 catch。这些非受检异常抛出后可以不用捕获,当然实际开发中只有没事做才自己写代码抛出这些非受检查型异常。当你知道自己的一个方法可能会发生某一种异常,但不想处理,可以使用throw声明这种异常,让调用这个方法的人自己处理。try catch只有异常发生时才会影响异常,因为发生了异常,肯定要构造异常对象,异常对象的构造,比如异常发生在哪一行,可能需要收集异常栈,无疑是一个耗时的操作。如果catch中return,finally也会执行。catch也抛出异常,fianlly一样执行。所以finally中一般做一些资源清理的工作,最好不在在finally在抛出异常或者执行return,因为finally抛出的异常会覆盖catch中的异常,return的返回值也会覆盖catch中return的值。

    0 赞同 0 条回复
  • Everglow 永久会员 2023年5月27日 上午11:03

    1.异常是指程序中出现的错误,因为java对异常进行了详细的分类所以通过异常可以使程序员确定错误发生的位置和原因,程序员就可以有针对性对这些异常进行处理

    2.异常可以分为error和exception

    error通常是指虚拟机发生的严重错误,我们无法通过修改程序对这些错误进行解决,常见的error有stcakoverflow,oom等,我们通常需要修改虚拟机的参数来解决

    exception是可以通过对程序进行调整而解决的,exception又可以分为受检异常和非受检严查,受检异常也可以叫做编译时异常,例如filenotfound exception 这些异常是要求程序在运行前就必须进行处理或向上抛出的,也就是说针对受检异常,我们必须要有对应的解决方案

    非受检异常是也可以叫做运行时异常,是指在程序运行时由于逻辑错误发生的异常,例如npe,程序编写时不需要处理,默认是将这些异常向上抛出,直到抛到虚拟机后打印出异常。

    3.throw是在一个方法体内制造出一个异常,throws是跟在方法参数列表后,表示方法中发生的这些异常统一向上(调用者)抛出。

    我的理解是,针对异常,我们可以有一个统一的解决方案,所以我们可以将异常都向上抛出之后统一处理,例如在我的springboot项目中,通过ControllerAdvice和ExcpetionHandler两个注解搭配使用,根据aop机制去处理所有在程序上游抛出的异常,交给异常处理方法去统一的处理

    4.不会吧?

    5.答案是会,无论如何finally块必须执行,举个例子,假如有一个变量i = 0,在catch块进行了i++紧接着return i

    但是后面finally块又执行了i++,那么假如程序进行了catch块 i = 1 之后想要直接return i但是发现finally还未执行,此时就会保存i = 1这个值等finally执行完再return,所以虽然在finally中 i++ 等于2了但是仍然会返回保留的值i = 1

    1 赞同 0 条回复
  • 秊 永久会员 2023年5月26日 下午11:10

    1、异常是程序在执行过程中可能发生的一些错误,它会暂时终止程序,并转到异常处理部分尝试恢复。异常的出现可以使我们把程序中可能出现错误的代码从正常代码中分离出来,单独进行处理。

    2、类似于 Object 类,Throwable 是所有异常的父类。下一层分为 Error 类和 Exception 类。

    Error 类表示严重的错误,一般由 JVM 和底层系统引发,并且不可恢复,例如内存溢出,class 没有主方法等。Exception 类是可以被程序捕获和处理的异常情况。

    Exception 再往下,按照异常的性质又分为编译异常 CheckedException 和运行时异常 RuntimeException。其中检查异常在编译阶段就能被检测出,例如 IO 异常 IOException,文件找不到异常 FileNotFoundException等。运行时异常只有在程序运行时才能被检测出,例如空指针异常 NullPointerException,数组下标越界 ArrayIndexOutOfBoundsException 等。

    3、throw 用在方法体内,表示某个地方需要抛出一个异常,是一个具体的动作。而 throws 用在方法声明后面,表示这个方法可能会抛出哪些异常,是一个声明。

    这个需要分情况对待。首先,对于能在方法内处理的异常,可以直接用 try catch,但对于在当前方法内无法处理的异常,我们只能选择抛出,将它交给方法调用者去处理。其次,有时多个方法可能会抛出相同类型的异常,如果每个方法都用 try catch 会非常冗余,这时可以在这些方法中只 throw,在调用这些方法的地方整体 try catch,统一进行处理。

    4、几乎不会,也就是程序没有异常时,try catch 加和不加性能几乎一样,只有在程序有异常需要捕获时才会影响性能。

    原因在于,处理异常的 catch 语句在 class 文件中是用异常表实现的。异常表有四个字段,分别是 From, To, Target 和 Type。From 和 To 分别对应 try 块对应的行号,如果其中有异常抛出,会跳转到 Target 对应的行号,也就是 catch 语句对应的位置,而这个异常的类型记录在 Type 中。如果程序在 try 中没有异常抛出,最终会通过一条 goto 指令跳转到 try catch 块后的语句继续执行,这一条 goto 指令性能的消耗可以忽略不计。如果有异常,才会去查异常表,再跳转到对应的 catch 块位置去执行,这个过程可能会影响性能。

    5、会的,无论 catch 块中有异常还是有返回语句,最终一定会在方法真正结束之前执行 finally。但是需要考虑一种特殊情况,就是如果 try 块中抛出了异常但没有被 catch 捕获,且此时 finally 中也抛出了异常,那么 finally 中的异常会覆盖掉 try 中的异常,成为这个方法最终抛出的异常。实践中需要注意一下这个异常覆盖问题。

    1 赞同 0 条回复

# 回答此问题

后才能回答