10个有关Java异常的最常见问题

1. 已检查异常 VS 未检查异常

简单来说,已检查异常必须被捕获或者声明抛出。未检查异常通常是由一些无法恢复的错误导致的,比如除0, 空引用等。已检查异常的一个非常重要的作用就是,强迫方法调用者去正确的处理可能出现的错误,从而提高程序的健壮性。比如,IOException就是常用的已经检查异常,而RuntimeException是典型的未检查异常。

2. 处理异常的最佳实践

如果一个异常可以被正确地处理,那么我们就应该去捕获它。反之则应当直接抛出,让方法的调用者来决定如何处理。


3. 为什么在try语句块中定义的变量无法在catch和finally中使用?

如下面一段代码,在try中声明了一个String类型的引用s,然后我们在catch中试图读取这个s。这样的代码是无法通过编译的:
try {
	File file = new File("path");
	FileInputStream fis = new FileInputStream(file);
	String s = "inside";
} catch (FileNotFoundException e) {
	e.printStackTrace();
	System.out.println(s);
}

这样设计的原因是,在运行中我们无法确定异常会在try语句块的哪一行代码中被抛出。假如在 File file = new File("path"); 这一行就抛出异常的话,那么try语句块剩下的语句都不会被执行,则s也就不会存在。所以try中的变量不允许在catch 或 finally 中引用。


4. 为什么Double.parseDouble(null)和Integer.parseInt(null)会抛出两个不同的异常?

这两个方法确实会抛不同的异常。这只不过是JDK的设计问题而已,没什么特别的,不用细扣。

Integer.parseInt(null); 
// throws java.lang.NumberFormatException: null
 
Double.parseDouble(null); 
// throws java.lang.NullPointerException

5. 常用的RuntimeException

比如
IllegalArgumentException
ArrayIndexOutOfBoundsException

经常被这样使用:
if (obj == null) {
   throw new IllegalArgumentException("obj can not be null");

6. 能在一个catch语句块中捕获多个异常吗?

只要catch的异常是被抛出异常的父类就可以。例如 catch(Exception ex) 就能通吃所有的异常,但不推荐这样。

7. 构造方法能抛异常吗?

可以。比如下面的代码:
class FileReader{
	public FileInputStream fis = null;
 
	public FileReader() throws IOException{
		File dir = new File(".");//get current directory
		File fin = new File(dir.getCanonicalPath() + File.separator + "not-existing-file.txt");
		fis = new FileInputStream(fin);
	}
}


8. 可以在finally语句块中抛异常吗?

可以。比如下面的代码就是合法的:
public static void main(String[] args) {
	File file1 = new File("path1");
	File file2 = new File("path2");
	try {
 
		FileInputStream fis = new FileInputStream(file1);
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} finally {
		try {
			FileInputStream fis = new FileInputStream(file2);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}

然而,为了可读性起见,我们最好把 finally 语句块中的 try...catch 封装到一个方法中去,然后直接在finally中调用此方法。如:
public static void main(String[] args) {
	File file1 = new File("path1");
	File file2 = new File("path2");
	try {
 
		FileInputStream fis = new FileInputStream(file1);
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} finally {
		methodThrowException();
	}
}

9. finally 语句块中可以写return语句吗?

答案是可以。

10. 为什么很多开发者在catch中只写一句printStackTrace()就完事了?

try {
     ...
} catch(Exception e) {
     e.printStackTrace();
}

很多人都去做的事,并不一定就是正确的。应当尽量避免上面的写法。回顾上面的第二点,如果感觉自己处理不好这个异常,那么应该直接抛出。

10个有关Java异常的最常见问题,布布扣,bubuko.com

10个有关Java异常的最常见问题

上一篇:python中@staticmethod 、@classmethod 与一般方法的区别


下一篇:堆和栈(Java数据结构)