欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java面试题之异常

程序员文章站 2022-03-06 18:03:52
...

java面试题之异常
在java中提供了一套异常处理机制,用来处理应用程序运行过程中出现的错误。
Throwable是异常机制中错误(Error)和异常(Exception)的根类,用来保存和描述异常信息(线程创建时线程执行堆栈的快照)。Throwable有两 个子类:Error(错误)和Exception(异常)。

Error和Exception的区别?

Error:通常由环境或者硬件出现问题造成的错误,应用无法处理和恢复这类错误。比如:系统崩溃,内存不足,堆栈溢出等等。
Exception:表示应用程序出现了问题,但还是可能处理和恢复的。比如:程序员可以捕获异常并处理掉异常。

运行时异常和编译时异常区别?

RuntimeException:运行时异常 表示程序在运行过程中可能出现的异常,但是java编译器不会检查这类异常。比如:NullPoniterException,ClassCastException等
编译时异常:java编译器会检查这类异常,必须处理(捕获异常或者抛出),否则编译不通过。
例如:程序员书写代码不规范,存在语法错误。
编译器检查到可能出现ClassNotFoundException,IOException等类型的异常。

异常处理中的关键字有那些?

异常处理中的关键字:try,catch,finally,throw,throws。
try:用来处理可能出现异常的代码。
catch:紧跟在try后面,如果try块中出现异常,则catch会捕获到该异常。
finally:无论前面是否发生异常,都会执行finally块中的代码(除非调用System.exit(0)),常用于资源的释放,流的关闭。
throw:用在方法内部,用来抛出一个指定的异常。
throws:用在方法签名的后面,用来抛出一系列的异常。

JVM是怎样处理异常的?

当一个方法中出现异常时,会创建一个异常对象,这个异常对象(异常名称、异常描述和异常发生时应用程序的状态等信息等)被抛给虚拟机JVM,JVM会顺着调用栈,去查找捕获该异常的代码。即查找看看有没有try-cath块来处理该异常,如果能找到,则在catch中处理异常,如果没有找到,则抛给JVM默认的异常处理器处理。

java处理异常的方式?

java处理异常的方式有两种:
1、通过try-catch块来捕获异常。
2、通过throws抛出异常,由程序调用者去处理异常。抛出的异常应该是原始异常类型或是其子类的异常类型。

throw和throws的区别?

throw:用在方法的内部,用来抛出一种异常,用来抛出方法或代码块中的异常。
throws:用在方法签名的后面,可以抛出多个异常。

try-catch-finally中,try中return了,finall还会执行吗?一定会被执行吗?

不管是try中return还是catch中return了,finally都会在return返回前执行。
如果finally之前调用了System.exit(0)或者应用程序异常退出则不会调用finally中的代码。

final、finally和finalize的区别?

final:可以修饰变量、方法、类,修饰变量表示该变量是一个常量不能够修改,修饰方法表示该方法不能够重写、修饰类表示该类不被继承。
finally:*一般和try-catch块一起使用,用在处理异常的时候,把一定要执行的代码放finally代码块中,无论是否发生异常,finally中的代码一定执行。常用与关闭资源。
finalize:*是Object类中的一个方法,用于垃圾回收器将对象从内清除之前做一些必要的工作。

ClassNotFoundException和NoClassDefFoundError的区别?

ClassNotFoundException:是受检查的异常,必须处理,需要通过try-catch代码块,来进行捕获和处理,或者在方法名后声明throws抛出该异常。当使用Class.forName,ClassLoader.loadClass动态加载类到内存的时候,传入的类路径中找不到该类,会抛出该异常。
**NoClassDefFoundError:**是Error类型的错误,是由JVM引起的,不应该尝试捕获这个错误。JVM或着ClassLoader尝试加载某个类时,内存中找不到该类的定义,意思是编译时该类还存在,但是运行时找不到了,可能是编译后被删除了。

常见的异常有哪些?

NullPointerException:空指针异常(RuntimeException)
ArithmeticException:算术异常(RuntimeException)
ClassCastException:类型转换异常(RuntimeException)
IndexOutOfBoundsException:索引越界异常(RuntimeException)
ArrayIndexOutOfBoundsException:数组下标越界异常(RuntimeException)
NumberFormatException:数字格式转换异常(RuntimeException)
ClassNotFoundException:找不到类异常
IOException:IO异常
OutOfMemoryError:内存不足错误
StackeOverflowError:堆栈溢出错误

如何自定义异常

1、继承Exception或着RuntimeException
继承Exception类需要调用者自己处理异常,如果调用者不需要处理异常可以继承RuntimeException。
2、重写构造方法

//此处用继承Exception举例,如果调用者不想处理异常,则可以继承RuntimeException,构造方法可以根据需要实现其中的部分或者全部
public class MyException extends Exception{
	public MyException (){	//构造方法1
 	}
	public MyException (String message){ //构造方法2
            super(message);
 	}
 	public MyException (String message,Throwable cause){ //构造方法3
            super(message,cause);
 	}
 	public MyException (Throwable cause){ //构造方法4
            super(cause);
 	}
}
异常处理的最佳实践

1、异常不要用来做流程控制,条件控制。说明:异常设计的初衷是解决程序运行中各种意外的情况,且异常的处理效率比条件判断方式低很多。

2、不要捕获运行时异常(RuntimeException)

3、catch时分清稳定代码和非稳定的代码,稳定代码是指无论如何不会出错的代码。对于非稳定的代码catch应区分异常类型。说明:对大段代码进行try-catch,是程序无法根据不同的异常做出正确异常处理,也不利于问题定位。

4、不要生吞异常。说明:捕获异常是为了处理它,不要捕获了却什么都不处理直接抛弃掉,如果不想处理它,可以将该异常抛给它的调用着。反例:

public void doNotIgnoreExceptions() {
    try {
        // do something
    } catch (NumberFormatException e) {
        //什么事情都不做,直接抛弃异常
    }
}

5、finally块中必须对资源对象、流对象进行关闭,有异常也要try-carch。jdk7及以上可以使用try-with-resources

public void closeResource() {
    FileInputStream inputStream = null;
    try {
        File file = new File("./tmp.txt");
        inputStream = new FileInputStream(file);
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                log.error(e);
            }
        }
    }
}
或者
public void closeResource() {
    File file = new File("./tmp.txt");
    try (FileInputStream inputStream = new FileInputStream(file);) {
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}

6、不要再finally块中使用return。说明:try块中的return语句执行成功后,并不是马上返回,而是继续执行finally块中的语句,如果此处存在return,则直接返回,无情丢掉了try块中的返回点。反例:

private int x = 0;
public int checkReturn() {
    try {
        // x`在这里插入代码片`等于1,此处不返回
        return ++x;
    } finally {
        // 返回的结果是2
        return ++x;
    }
}

7、捕获异常和抛出异常,必须是完全匹配的,或者捕获异常是抛出异常的父类。