异常处理面试题详解

  1. 下列哪种异常是检查型异常,需要在编写程序时声明()
    A. NullPointerException
    B. ClassCastException
    C. FileNotFoundException
    D. IndexOutOfBoundsException
    答案:C
    分析:NullPointerException 空指针异常
    ClassCastException 类型转换异常
    IndexOutOfBoundsException 索引超出边界的异常
    以上这些异常都是程序在运行时发生的异常,所以不需要在编写程序时声
  2. Java 出现 OutOf MemoryError(OOM 错误)的原因有哪
    些?出现 OOM 错误后,怎么解决?
    答:
    OutOf MemoryError 这种错误可以细分为多种不同的错误,每种错误都有
    自身的原因和解决办法,如下所示:
    java.lang.OutOfMemoryError: Java heap space
    错误原因:此 OOM 是由于 JVM 中 heap 的最大值不满足需要。
    解决方法:1) 调高 heap 的最大值,即-Xmx 的值调大。2) 如果你的程序
    存在内存泄漏,一味的增加 heap 空间也只是推迟该错误出现的时间而已,
    所以要检查程序是否存在内存泄漏。
    java.lang.OutOfMemoryError: GC overhead limit exceeded
    错误原因:此 OOM 是由于 JVM 在 GC 时,对象过多,导致内存溢出,建
    议调整 GC 的策略,在一定比例下开始 GC 而不要使用默认的策略,或者将
    新代和老代设置合适的大小,需要进行微调存活率。
    解决方法:改变 GC 策略,在老代 80%时就是开始 GC,并且将
    -XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio
    (-XX:NewRatio=4)设置的更合理。
    java.lang.OutOfMemoryError: Java perm space
    错误原因:此 OOM 是由于 JVM 中 perm 的最大值不满足需要。
    解决方法:调高 heap 的最大值,即-XX:MaxPermSize 的值调大。
    另外,注意一点,Perm 一般是在 JVM 启动时加载类进来,如果是 JVM 运
    行较长一段时间而不是刚启动后溢出的话,很有可能是由于运行时有类被动
    态加载进来,此时建议用 CMS 策略中的类卸载配置。如:
    -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled。 java.lang.OutOfMemoryError: unable to create new native thread
    错误原因:当 JVM 向 OS 请求创建一个新线程时,而 OS 却由于内存不足无
    法创建新的 native 线程。
    解决方法:如果 JVM 内存调的过大或者可利用率小于 20%,可以建议将
    heap及perm的最大值下调,并将线程栈调小,即-Xss调小,如:-Xss128k。
    java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    错误原因:此类信息表明应用程序(或者被应用程序调用的 APIs)试图分配
    一个大于堆大小的数组。例如,如果应用程序 new 一个数组对象,大小为
    512M,但是最大堆大小为 256M,因此 OutOfMemoryError 会抛出,因
    为数组的大小超过虚拟机的限制。
    解决方法:1) 首先检查 heap 的-Xmx 是不是设置的过小。2) 如果 heap
    的-Xmx 已经足够大,那么请检查应用程序是不是存在 bug,例如:应用程
    序可能在计算数组的大小时,存在算法错误,导致数组的 size 很大,从而导
    致巨大的数组被分配。
    java.lang.OutOfMemoryError: request bytes for .
    Out of swap space
    错误原因:抛出这类错误,是由于从 native 堆中分配内存失败,并且堆内
    存可能接近耗尽。这类错误可能跟应用程序没有关系,例如下面两种原因也
    会导致错误的发生:1) 操作系统配置了较小的交换区。2)系统的另外一个
    进程正在消耗所有的内存。
    解决办法:1) 检查 os 的 swap 是不是没有设置或者设置的过小。2) 检查
    是否有其他进程在消耗大量的内存,从而导致当前的 JVM 内存不够分配。
    注意:虽然有时部分显示导致 OOM 的原因,但大多数情况下,
    显示的是提示分配失败的源模块的名称,所以有必要查看日志文
    件,如 crash 时的 hs 文件。
  3. 列举常见的运行时异常
    答:
    ClassCastException(类转换异常)
    比如 Object obj=new Object(); String s=(String)obj;
    IndexOutOfBoundsException(下标越界异常)
    NullPointerException(空指针异常)
    ArrayStoreException(数据存储异常,操作数组时类型不一致)
    BufferOverflowException(IO 操作时出现的缓冲区上溢异常)
    InputMismatchException(输入类型不匹配异常)
    ArithmeticException(算术异常)
    注意:运行时异常都是 RuntimeException 子类异常。
  4. 下面关于 Java.lang.Exception 类的说法正确的是()
    A. 继承自 Throwable
    B. 不支持 Serializable
    C. 继承自 AbstractSet
    D. 继承自 FitelnputStream
    答案:A
    分析:
    Throwable 是 Exception 和 Error 的父类,Exception 虽然没有实现
    Serializable 接口,但是其父类 Throwable 已经实现了该接口,因此
    Exception 也支持 Serializable。
  5. Unsupported major.minor version 52 是什么异常,怎么
    造成的,如何解决?
    答:问题的根本原因是工程中某个 jar 包的版本(jar 包编译时的所用的 jdk
    版本)高于工程 build path 中 jdk 的版本,这个是不兼容的! 编程中遇到此
    异常 Unsupported major.minor version 52.0(根据版本号,这里可以为
    其他数值,52 是 1.8jdk jar 包与 1.8 以下低版本 jdk 不匹配),在将 build
    path 中 jdk 的版本调整与 jar 包匹配后,解决异常。
  6. try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally{}
    里的 code 会不会被执行,什么时候被执行,在 return 前还是后?
    答:会执行,在方法返回调用者前执行。Java 允许在 finally 中改变返回值
    的做法是不好的,因为如果存在 finally 代码块,try 中的 return 语句不会立
    马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用
    者返回其值,然后如果在 finally 中修改了返回值,这会对程序造成很大的
    困扰,C#中就从语法上规定不能做这样的事。
    (也许你的答案是在 return 之前,但往更细地说,我的答案是在 return 中间
    执行,请看下面程序代码的运行结果:
    public classTest {
    /**
  • @paramargs add by zxx ,Dec 9, 2008
    */
    public static voidmain(String[] args) {
    // TODO Auto-generated method stub
    System.out.println(newTest().test());;
    }
    static int test()
    {
    int x = 1;
    try
    {
    returnx;
    }
    finally
    {
    ++x;
    }
    }

}
---------执行结果 ---------
1
运行结果是 1,为什么呢?主函数调用子函数并得到结果的过程,好比主函
数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再
将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函
数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。
285. Java 语言如何进行异常处理,关键字:throws、throw、try、
catch、finally 分别如何使用?
答:Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,
并提供了良好的接口。在 Java 中,每个异常都是一个对象,它是 Throwable
类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中
包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。
Java 的异常处理是通过 5 个关键词来实现的:try、catch、throw、throws
和 finally。一般情况下是用 try 来执行一段程序,如果出现异常,系统会抛
出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,
或最后(finally)由缺省处理器来处理;try 用来指定一块预防所有“异常”
的程序;catch 子句紧跟在 try 块后面,用来指定你想要捕捉的“异常”的
类型;throw 语句用来明确地抛出一个“异常”;throws 用来标明一个成
员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么
“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个 try 语
句,在这个成员函数内部写另一个 try 语句保护其他代码。每当遇到一个 try
语句,“异常”的框架就放到栈上面,直到所有的 try 语句都完成。如果下
一级的 try 语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处
理这种“异常”的 try 语句。
286. 运行时异常与受检异常有何异同?
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟
机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没
有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序
设计无误,仍然可能因使用的问题而引发。Java 编译器要求方法必须声明抛
出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。
异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《Effective
Java》中对异常的使用给出了以下指导原则:
• 不要将异常处理用于正常的控制流(设计良好的 API 不应该强迫它的调
用者为了正常的控制流而使用异常)
• 对可以恢复的情况使用受检异常,对编程错误使用运行时异常
• 避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常发生)
• 优先使用标准的异常
• 每个方法抛出的异常都要有文档
• 保持异常的原子性
• 不要在 catch 中忽略掉捕获到的异常
(异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的
通常操作中可能遇到的异常,是一种常见运行错误。java 编译器要求方法必
须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获
的运行时异常。)
287. 类 ExampleA 继承 Exception,类 ExampleB 继承
ExampleA
有如下代码片断:
try{
throw new ExampleB("b")
}catch(ExampleA e){
System.out.println("ExampleA");
}catch(Exception e){
System.out.println("Exception");
}
}
请问执行此段代码的输出是什么?
答:输出:ExampleA。(根据里氏代换原则[能使用父类型的地方一定能使
用子类型],抓取 ExampleA 类型异常的 catch 块能够抓住 try 块中抛出的
ExampleB 类型的异常)
补充: 比此题略复杂的一道面试题如下所示(此题的出处是《Java 编程思
想》),说出你的答案吧!
package com.bjsxt;
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
class Human {
public static void main(String[] args)
throws Exception {
try {
try {
throw new Sneeze();
}
catch ( Annoyance a ) {
System.out.println("Caught Annoyance");
throw a;
}
}
catch ( Sneeze s ) {
System.out.println("Caught Sneeze");
return ;
}
finally {
System.out.println("Hello World!");
}
}
}
输出为:
Caught Annoyance
Caught Sneeze
Hello World!
288. Error 和 Exception 的区别
Error 类,表示仅靠程序本身无法恢复的严重错误,比如说内存溢出、动
态链接异常、虚拟机错误。应用程序不应该抛出这种类型的对象。假如出现
这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在
进行程序设计时,应该更关注 Exception 类。
Exception 类,由 Java 应用程序抛出和处理的非严重错误,比如所需文
件没有找到、零作除数,数组下标越界等。它的各种不同子类分别对应不同
类型异常。可分为两类:Checked 异常和 Runtime 异常
289. Java 异常处理 try-catch-finally 的执行过程
try-catch-finally 程序块的执行流程以及执行结果比较复杂。
基本执行过程如下:
1)程序首先执行可能发生异常的 try 语句块。
2)如果 try 语句没有出现异常则执行完后跳至 finally 语句块执行;
3)如果 try 语句出现异常,则中断执行并根据发生的异常类型跳至相应的
catch 语句块执行处理。
4)catch 语句块可以有多个,分别捕获不同类型的异常。
5)catch 语句块执行完后程序会继续执行 finally 语句块。
finally 语句是可选的,如果有的话,则不管是否发生异常,finally 语句都会
被执行。需要注意的是即使 try 和 catch 块中存在 return 语句,finally 语
句也会执行,是在执行完 finally 语句后再通过 return 退出。
290. 异常处理中 throws 和 throw 的区别
1)作用不同:
throw 用于程序员自行产生并抛出异常;
throws 用于声明在该方法内抛出了异常
2) 使用的位置不同:
throw 位于方法体内部,可以作为单独语句使用;
throws 必须跟在方法参数列表的后面,不能单独使用。
3)内容不同:
throw 抛出一个异常对象,且只能是一个;
throws 后面跟异常类,而且可以有多个

原文地址:https://www.cnblogs.com/linanana/p/12545990.html