乐趣区

10.Java异常问题

目录介绍

10.0.0.1 见过哪些运行时异常?异常处理机制知道哪些?从异常是否必须需要被处理的角度来看怎么分类?
10.0.0.2 运用 Java 异常处理机制?异常处理的原理?Java 中检查异常和非检查异常的区别?
10.0.0.3 异常处理的过程中,你遵循那些好的实践?throw 和 throws 这两个关键字在 java 中有什么不同?
10.0.0.4 你知道什么是“异常链”吗?自定义实现过哪些异常,怎么写的? 可以有一个空的 catch 块吗?
10.0.0.5 Java 异常类有哪些的重要方法?导致“主线程中的异常”的不同场景是什么?
10.0.0.6 看下面这段子类继承父类代码有什么问题?针对抛异常是 IOException 还是 Exception,能随便写吗,结合案例说一下?
10.0.0.7 捕获异常时,为何在 catch 中要注意异常层级关系?需要注意哪些问题?

好消息

博客笔记大汇总【15 年 10 月到至今】,包括 Java 基础及深入知识点,Android 技术博客,Python 学习笔记等等,还包括平时开发中遇到的 bug 汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是 markdown 格式的!同时也开源了生活博客,从 12 年起,积累共计 500 篇 [近 100 万字],将会陆续发表到网上,转载请注明出处,谢谢!
链接地址:https://github.com/yangchong2…
如果觉得好,可以 star 一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有博客将陆续开源到 GitHub!

10.0.0.1 见过哪些运行时异常?异常处理机制知道哪些?从异常是否必须需要被处理的角度来看怎么分类?

运行时异常:Throwable 继承层次结构,可见分成两大类 Error 和 Exception:

Error(错误): 指程序无法恢复的异常情况,表示运行应用程序中较严重的问题;发生于虚拟机自身、或者在虚拟机试图执行应用时,如 Virtual MachineError(Java 虚拟机运行错误)、NoClassDefFoundError(类定义错误);属于不可查异常,即不强制程序员必须处理,即使不处理也不会出现语法错误。

Exception(异常): 指程序有可能恢复的异常情况,表示程序本身可以处理的异常。又分两大类:

RuntimeException(运行时异常):由程序自身的问题导致产生的异常;如 NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常);属于不可查异常。
非运行时异常:由程序外部的问题引起的异常;除了 RuntimeException 以外的异常,如 FileNotFoundException(文件不存在异常);属于可查异常,即强制程序员必须进行处理,如果不进行处理则会出现语法错误。

异常处理机制

捕捉异常:由系统自动抛出异常,即 try 捕获异常 ->catch 处理异常 ->finally 最终处理
抛出异常:在方法中将异常对象显性地抛出,之后异常会沿着调用层次向上抛出,交由调用它的方法来处理。配合 throws 声明抛出的异常和 throw 抛出异常
自定义异常:继承 Execption 类或其子类
技术博客大总结

从异常是否必须需要被处理的角度来看怎么分类

异常又可分为不受检查异常和受检查异常两种情况:

不受检查异常:派生于 Error 或 RuntimeException 的所有异常;
受检查异常:除去不受检查异常的所有异常。

10.0.0.2 运用 Java 异常处理机制?异常处理的原理?Java 中检查异常和非检查异常的区别?

运用 Java 异常处理机制?

1.try…catch 语句
2.finally 语句:大多数情况下都必须执行的代码
3.throws 子句:声明可能发生的异常类
4.throw: 抛出具体的异常对象。

异常处理的原理?
Java 虚拟机用方法调用栈(method invocation stack)来跟踪每个线程中一系列的方法调用过程。如果在执行方法过程中抛出异常,则 Java 虚拟机必须找到能捕获该异常的 catch 代码块。当 Java 虚拟机追溯到调用栈的底部的方法的时候,如果仍然没有找到处理该异常的代码块,这样它就会按步骤处理,首先会打印方法调用栈的异常信息,然后如果所处的线程不是主线程,那么就会终止这个线程。

Java 中检查异常和非检查异常的区别

检查型异常(CheckedException)

在 Java 中所有不是 RuntimeException 派生的 Exception 都是检查型异常。当函数中存在抛出检查型异常的操作时该函数的函数声明中必须包含 throws 语句。调用改函数的函数也必须对该异常进行处理,如不进行处理则必须在调用函数上声明 throws 语句。
检查型异常是 JAVA 首创的,在编译期对异常的处理有强制性的要求。在 JDK 代码中大量的异常属于检查型异常,包括 IOException,SQLException 等等。

非检查型异常(UncheckedException)技术博客大总结

在 Java 中所有 RuntimeException 的派生类都是非检查型异常,与检查型异常对比,非检查型异常可以不在函数声明中添加 throws 语句,调用函数上也不需要强制处理。
常见的 NullPointException,ClassCastException 是常见的非检查型异常。非检查型异常可以不使用 try…catch 进行处理,但是如果有异常产生,则异常将由 JVM 进行处理。对于 RuntimeException 的子类最好也使用异常处理机制。虽然 RuntimeException 的异常可以不使用 try…catch 进行处理,但是如果一旦发生异常,则肯定会导致程序中断执行,所以,为了保证程序再出错后依然可以执行,在开发代码时最好使用 try…catch 的异常处理机制进行处理。

10.0.0.3 异常处理的过程中,你遵循那些好的实践?throw 和 throws 这两个关键字在 java 中有什么不同?

异常处理的过程中,你遵循那些好的实践?

异常处理在项目设计中是非常关键的,所以精通异常处理是十分必要的。异常处理有很多最佳实践,下面列举集中,它们提高你代码的健壮性和灵活性:
1) 调用方法的时候返回布尔值来代替返回 null,这样可以 NullPointerException。由于空指针是 java 异常里最恶心的异常。
2) catch 块里别不写代码。空 catch 块是异常处理里的错误事件,因为它只是捕获了异常,却没有任何处理或者提示。通常你起码要打印出异常信息,当然你最好根据需求对异常信息进行处理。
3) 能抛受控异常(checked Exception)就尽量不抛受非控异常 (checked Exception)。通过去掉重复的异常处理代码,可以提高代码的可读性。
4) 绝对不要让你的数据库相关异常显示到客户端。由于绝大多数数据库和 SQLException 异常都是受控异常,在 Java 中,你应该在 DAO 层把异常信息处理,然后返回处理过的能让用户看懂并根据异常提示信息改正操作的异常信息。
5) 在 Java 中,一定要在数据库连接,数据库查询,流处理后,在 finally 块中调用 close() 方法。

throw 和 throws 这两个关键字在 java 中有什么不同?

技术博客大总结
throws 总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常,你也可以申明未检查的异常,但这不是编译器强制的。如果方法抛出了异常那么调用这个方法的时候就需要将这个异常处理。
throw 是用来抛出任意异常的,按照语法你可以抛出任意 Throwable (Throwable 或任何 Throwable 的衍生类) , throw 可以中断程序运行,因此可以用来代替 return。

private static voidshow() {
throw new UnsupportedOperationException(“抛出异常”);
}

10.0.0.4 你知道什么是“异常链”吗?自定义实现过哪些异常,怎么写的? 可以有一个空的 catch 块吗?

你知道什么是“异常链”吗?
“异常链”是 Java 中非常流行的异常处理概念,是指在进行一个异常处理时抛出了另外一个异常,由此产生了一个异常链条。该技术大多用于将“受检查异常”(checked exception)封装成为“非受检查异常”(unchecked exception) 或者 RuntimeException。顺便说一下,如果因为因为异常你决定抛出一个新的异常,你一定要包含原有的异常,这样,处理程序才可以通过 getCause() 和 initCause() 方法来访问异常最终的根源。

自定义实现过哪些异常?

可以有一个空的 catch 块吗?

可以有一个空的 catch 块,但这是最糟糕的编程的例子。不应该有空的 catch 块,因为如果异常被该块捕获,我们将没有关于异常的信息,它将成为调试它的噩梦。应该至少有一个日志记录语句来记录控制台或日志文件中的异常详细信息。
技术博客大总结

10.0.0.5 Java 异常类有哪些的重要方法?导致“主线程中的异常”的不同场景是什么?

Java 异常类有哪些的重要方法?

Exception 和它的所有子类没有提供任何特殊方法供使用,它们的所有方法都是来自其基类 Throwable。

String getMessage(): 方法返回 Throwable 的 String 型信息,当异常通过构造器创建后可用。
String getLocalizedMessage():此方法通过被重写来得到用本地语言表示的异常信息返回给调用程序。Throwable 类通常只是用 getMessage() 方法来实现返回异常信息。
synchronized Throwable getCause(): 此方法返回异常产生的原因,如果不知道原因的话返回 null。( 原文有拼写错误 应该是 if 不是 id)
String toString(): 方法返回 String 格式的 Throwable 信息,此信息包括 Throwable 的名字和本地化信息。
void printStackTrace():该方法打印栈轨迹信息到标准错误流。该方法能接受 PrintStream 和 PrintWriter 作为参数实现重载,这样就能实现打印栈轨迹到文件或流中。

导致“主线程中的异常”的不同场景是什么?

一些常见的主线程异常情况是:

线程 main java.lang.UnsupportedClassVersionError 中的异常:当您的 java 类从另一个 JDK 版本编译并且您试图从另一个 java 版本运行它时,会出现此异常。
线程 main java.lang.NoClassDefFoundError 中的异常:此异常有两种变体。第一个是你提供扩展名为.class 的类全名的地方。第二种情况是没有找到类。
线程 main java.lang.NoSuchMethodError 中的异常:main:当您尝试运行一个没有 main 方法的类时,会出现此异常。
技术博客大总结
线程“main”中的异常 java.lang.ArithmeticException:无论何时从 main 方法抛出任何异常,它都会打印出异常是 console。第一部分解释了异常从 main 方法抛出,第二部分打印异常类名称,然后在冒号后打印异常消息。

10.0.0.6 看下面这段子类继承父类代码有什么问题?针对抛异常是 IOException 还是 Exception,能随便写吗,结合案例说一下?

看下面这段代码有什么问题?
public class SuperClass {
public void start() throws IOException{
throw new IOException(“Not able to open file”);
}
}

public class SubClass extends SuperClass{
public void start() throws Exception{
throw new Exception(“Not able to start”);
}
}
这段代码编译器将对子类覆盖 start 方法产生错误。因为每个 Java 中方法的覆盖是有规则的,一个覆盖的方法不能抛出的异常比原方法继承关系高。因为这里的 start 方法在超类中抛出了 IOException,所有在子类中的 start 方法只能抛出要么是 IOExcepition 或是其子类,但不能是其超类,如 Exception。

针对抛异常是 IOException 还是 Exception,能随便写吗,结合案例说一下?
肯定不要随便写,容易造成迷惑性。下面看看代码,举个简单的案例!技术博客大总结

public static void start(){
System.out.println(“Java Exception”);
}

public static void main(String args[]) {
try{
start();
}catch(IOException e){
e.printStackTrace();
}
}
上面的 Java 异常例子代码中,编译器将在处理 IOException 时报错,因为 IOException 是受检查异常,而 start 方法并没有抛出 IOException,所以编译器将抛出“异常,java.io.IOException 不会在 try 语句体中抛出”,但是如果你将 IOException 改为 Exception,编译器报错将消失,因为 Exception 可以用来捕捉所有运行时异常,这样就不需要声明抛出语句。我喜欢这样带有迷惑性的 Java 异常面试题,因为它不会让人轻易的找出是 IOException 还是 Exception。你也可以在 JoshuaBloach 和 NeilGafter 的 Java 谜题中找到一些有关 Java 错误和异常的具有迷惑性问题。

10.0.0.7 捕获异常时,为何在 catch 中要注意异常层级关系?需要注意哪些问题?

捕获异常时,为何在 catch 中要注意异常层级关系?需要注意哪些问题?

注意,catch 中一定要注意层级关系。这里举一个简单的案例,就可以很好的理解为何要注重层级问题呢!
技术博客大总结

public static void start() throws IOException, RuntimeException{
throw new RuntimeException(“Not able to Start”);
}

public static void main(String args[]) {
try {
start();
} catch (Exception e) {
e.printStackTrace();
} catch (RuntimeException e2) {
e2.printStackTrace();
}
}
这段代码会在捕捉异常代码块的 RuntimeException 类型变量“e2”里抛出编译异常错误。因为 Exception 是 RuntimeException 的超类,在 start 方法中所有的 RuntimeException 会被第一个捕捉异常块捕捉,这样就无法到达第二个捕捉块,这就是抛出“exception java.lang.RuntimeException has already been caught”的编译错误原因。

其他介绍
01. 关于博客汇总链接

1. 技术博客汇总

2. 开源项目汇总

3. 生活博客汇总

4. 喜马拉雅音频汇总

5. 其他汇总

02. 关于我的博客

我的个人站点:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/…

简书:http://www.jianshu.com/u/b7b2…

csdn:http://my.csdn.net/m0_37700275

喜马拉雅听书:http://www.ximalaya.com/zhubo…

开源中国:https://my.oschina.net/zbj161…

泡在网上的日子:http://www.jcodecraeer.com/me…

邮箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a… 239.headeruserinfo.3.dT4bcV
segmentfault 头条:https://segmentfault.com/u/xi…

掘金:https://juejin.im/user/593943…

退出移动版