异常


在这里插入图片描述
什么是 Throwable

Throwable 类是 Java 语言中所有错误(errors)和异常(exceptions)的父类。只有继承于 Throwable 的类或者其子类才能够被抛出,还有一种方式是带有 Java 中的 @throw 注解的类也可以抛出。
在Java规范中,对非受查异常和受查异常的定义是这样的:
“The unchecked exception classes are the run-time exception classes and the error classes.
“The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are Throwable and all its subclasses other than RuntimeException and its subclasses and Errorand its subclasses.
也就是说,除了 RuntimeException 和其子类,以及error和其子类,其它的所有异常都是 checkedException。
那么,按照这种逻辑关系,我们可以对 Throwable 及其子类进行归类分析
在 Java 中的基本理念是 结构不佳的代码不能运行,发现错误的理想时期是在编译期间,因为你不用运行程序,只是凭借着对 Java 基本理念的理解就能发现问题。但是编译期并不能找出所有的问题,有一些 NullPointerException 和 ClassNotFoundException 在编译期找不到,这些异常是 RuntimeException 运行时异常,这些异常往往在运行时才能被发现。
我们写 Java 程序经常会出现两种问题,一种是 java.lang.Exception ,一种是 java.lang.Error,都用来表示出现了异常情况,下面就针对这两种概念进行理解。
认识 Exception

Exception 位于 java.lang 包下,它是一种顶级接口,继承于 Throwable 类,Exception 类及其子类都是 Throwable 的组成条件,是程序出现的合理情况。
在认识 Exception 之前,有必要先了解一下什么是 Throwable。常见的 Exception

下面我们回到 Exception 的探讨上来,现在你知道了 Exception 的父类是 Throwable,并且 Exception 有两种异常,一种是 RuntimeException ;一种是 CheckedException,这两种异常都应该去捕获。
下面列出了一些 Java 中常见的异常及其分类,这块面试官也可能让你举出几个常见的异常情况并将其分类
RuntimeException
序号 异常名称 异常描述
1 ArrayIndexOutOfBoundsException 数组越界异常
2 NullPointerException 空指针异常
3 IllegalArgumentException 非法参数异常
4 NegativeArraySizeException 数组长度为负异常
5 IllegalStateException 非法状态异常
6 ClassCastException 类型转换异常
UncheckedException
序号 异常名称 异常描述
1 NoSuchFieldException 表示该类没有指定名称抛出来的异常
2 NoSuchMethodException 表示该类没有指定方法抛出来的异常
3 IllegalAccessException 不允许访问某个类的异常
4 ClassNotFoundException 类没有找到抛出异常
与 Exception 有关的 Java 关键字

那么 Java 中是如何处理这些异常的呢?在 Java 中有这几个关键字 throws、throw、try、finally、catch 下面我们分别来探讨一下
异常处理的原则

我们在日常处理异常的代码中,应该遵循三个原则
不要捕获类似 Exception 之类的异常,而应该捕获类似特定的异常,比如 InterruptedException,方便排查问题,而且也能够让其他人接手你的代码时,会减少骂你的次数。
不要生吞异常。这是异常处理中要特别注重的事情。如果我们不把异常抛出来,或者也没有输出到 Logger 日志中,程序可能会在后面以不可控的方式结束。
不要在函数式编程中使用 checkedException。

在这里插入图片描述
其中包括两部分,由所有线程共享的数据区和线程隔离的数据区组成,在上面的 Java 内存模型中,只有程序计数器是不会发生 OutOfMemoryError 情况的区域,程序计数器控制着计算机指令的分支、循环、跳转、异常处理和线程恢复,并且程序计数器是每个线程私有的。
“什么是线程私有:表示的就是各条线程之间互不影响,独立存储的内存区域。
如果应用程序执行的是 Java 方法,那么这个计数器记录的就是虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器值则为空(Undefined)。
除了程序计数器外,其他区域:方法区(Method Area)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack) 和 堆(Heap) 都是可能发生 OutOfMemoryError 的区域。
虚拟机栈:如果线程请求的栈深度大于虚拟机栈所允许的深度,将会出现 StackOverflowError 异常;如果虚拟机动态扩展无法申请到足够的内存,将出现 OutOfMemoryError。
本地方法栈和虚拟机栈一样
堆:Java 堆可以处于物理上不连续,逻辑上连续,就像我们的磁盘空间一样,如果堆中没有内存完成实例分配,并且堆无法扩展时,将会抛出 OutOfMemoryError。
方法区:方法区无法满足内存分配需求时,将抛出 OutOfMemoryError 异常。
一道经典的面试题

一道非常经典的面试题,NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
在类的加载过程中, JVM 或者 ClassLoader 无法找到对应的类时,都可能会引起这两种异常/错误,由于不同的 ClassLoader 会从不同的地方加载类,有时是错误的 CLASSPATH 类路径导致的这类错误,有时是某个库的 jar 包缺失引发这类错误。NoClassDefFoundError 表示这个类在编译时期存在,但是在运行时却找不到此类,有时静态初始化块也会导致 NoClassDefFoundError 错误。
“ClassLoader 是类路径装载器,在Java 中,类路径装载器一共有三种两类一种是虚拟机自带的 ClassLoader,分为三种
启动类加载器(Bootstrap) ,负责加载 $JAVAHOME/jre/lib/rt.jar
扩展类加载器(Extension),负责加载 $JAVAHOME/jre/lib/ext/*.jar
应用程序类加载器(AppClassLoader),加载当前应用的 classpath 的所有类
第二种是用户自定义类加载器
Java.lang.ClassLoader 的子类,用户可以定制类的加载方式。
在这里插入图片描述
另一方面,ClassNotFoundException 与编译时期无关,当你尝试在运行时使用反射加载类时,ClassNotFoundException 就会出现。
简而言之,ClassNotFoundException 和 NoClassDefFoundError 都是由 CLASSPATH 中缺少类引起的,通常是由于缺少 JAR 文件而引起的,但是如果 JVM 认为应用运行时找不到相应的引用,就会抛出 NoClassDefFoundError 错误;当你在代码中显示的加载类比如 Class.forName() 调用时却没有找到相应的类,就会抛出 java.lang.ClassNotFoundException。
NoClassDefFoundError 是 JVM 引起的错误,是 unchecked,未经检查的。因此不会使用 try-catch 或者 finally 语句块;另外,ClassNotFoundException 是受检异常,因此需要 try-catch 语句块或者 try-finally 语句块包围,否则会导致编译错误。
调用 Class.forName()、ClassLoader.findClass() 和 ClassLoader.loadClass() 等方法时可能会引起 java.lang.ClassNotFoundException,如图所示
在这里插入图片描述
NoClassDefFoundError 是链接错误,发生在链接阶段,当解析引用找不到对应的类,就会触发;而 ClassNotFoundException 是发生在运行时的异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值