JavaSE入门级-第十课-异常处理和垃圾回收
前言
在程序设计和运行过程中,错误是不可避免的,尽管java的的健壮性要求需要编译后才能执行,但是有些程序它没有违反语法问题却也能出错,因此java提供了异常机制,让研发人员可以不会因为程序发生异常就导致程序终止
认识异常
看下面一段程序:

这是一个空指针异常,在语法范畴内是可以编译通过的,但是运行会终止,并且往后的代码都不会执行,线程会中断
此类的问题还有很多种:
l 除0异常

l 格式异常

异常的超类
在java中针对所有的异常问题,或者说错误问题,都已经被成功定义出来,所以一旦程序发生异常,jvm会产生一个异常对象
我们看一下异常的类型图:

java.lang.Throwable
继承于Object,是所有异常的超类,它定义了异常的规范
l getMessage() 方法
获取异常信息,日志 或 控制台展现使用
l printStackTrace() 方法
打印栈异常轨迹,在面向对象编程中方法层层调用,最先运行的一定是最底层的方法,而这个方法往往不是研发人员编写的,所以底层的方法报错入栈底,输出的报错信息则是从栈顶开始,所以有金句良言,报错看第一行
l 实例代码:

java.lang.Error
Throwable 的子类,表示严重的问题,这种问题代码调试无法解决
l 实例代码:

(注意:我们在编码过程中 很少 关注错误,了解便可)
java.lang.Exception
Throwable的子类,表示异常,我们平时说的异常指的就是 Exception
代码和实例和Exception差不多,这里不再演示
处理异常
java程序发生异常会被终止,虚拟机会根据发生的问题,构造出对应的异常对象,在控制台打印出来,帮助研发人员找到问题
相亲现场

我们可以预感到,这对于女主角来说是一个悲剧,避免悲剧发生,处理异常

l 运行结果:

虽然也报错了,但是男主角该说的话还是说完了,因为我们处理了异常
try-catch-finally

java提供了特定的语句块帮助我们处理异常
l try
表示可能发生异常的语句快,如果发生异常jvm产生的异常对象会被catch捕获
l catch
捕获try部分发生的异常,必须匹配,注意向上转型是允许的
l finally
无论如何都会执行的部分,除非程序被终止
l 实例实例:解决用户登入会空指针的问题
值得注意的问题
l try 必须要有而且只能有一个
l finally 可以没有,也只能有一个
l catch 可以没有,可以有多个
l 语句块要连续,不能在中间加入其它代码
l 代码实例:

最正确的捕获异常

疑难点
try-catch-finally在工作中应用频率很高,它本身没有什么难点,但是有一些考试或者面试会拿语法做文章
l 赋诗一首

(注意:finally无论如何都会运行,try部分发生异常后面语句不执行)
练习
l 实现计算器,要求不会因为异常而中断
运行时异常
java中有一类异常 RuntimeException,它是Exception的子类,是指在jvm运行期间发生的异常,这种异常在编译的时候不需要额外操作,例如空指针,除0都是属于这类异常
练习
记住5个运行时异常
非运行时异常
CheckedException也称为可控异常,这种异常在编译时要求我们进行显示的try-catch,其实在jvm和第三方合作的时候,例如:文件 IO SQL 都会要求可控式异常
练习
记住5个非运行时异常
方法抛出异常
如果语句出现异常我们可以往外面抛出
l 使用关键字 throws + 具体的异常类型
示例代码:葫芦娃没有8娃 你不能创建8娃

l 主动抛出异常
上图中我们也能看到在方法内可以 主动 throw 一个异常对象
自定义异常
在上文中,制造葫芦娃错误,这是一个我们自己捏造的异常,不属于jvm现有的范围,我们可以主动早就一个异常类。
自定义异常步骤
l 选择一个继承的父类(运行时? 非运行时? 或者超类?)
只有Thorwable的子类才会被jvm抛出
l 必须重写 getMessage 和 printStackTrace 方法(规定)
l 代码实例:

(提醒:想怎么写就怎么写)
断言
assert断言,为程序做一个预期
实例代码:

(注意:当 断言条件为false 时会输出对应结果)
l 断言运行配置:


java垃圾回收机制
垃圾指的是失去引用的数据,永久的待在了内存中,就是垃圾,我们应该把他们清理出去,java提供了垃圾回收,garbage collection简称gc,有4种之多
java中的内存
jdk1.8之后常量池移动到了堆中

引用类型数据
引用类型数据在栈中保持一个引用,
l 强引用
StrongReference 明显的引用指向,垃圾回收机制不会回收
代码举例:直接new 就是强引用
l 软引用
SoftReference 内存充足的时候不会回收
代码举例:

l 弱引用
WeakReference 只要垃圾回收机制一运行,一定会被回收
代码举例:

l 虚引用
PhantomReference 需要配合队列来实现,单独的虚引用,可以说是没有引用
代码举例:

垃圾回收算法
垃圾回收算法经过多次更替,即垃圾回收策略
l 引用计数法
存在一个引用 +1 失去一个引用 -1,当引用为0时确定为垃圾
l 复制法
区分两块内存,有引用的对象复制到另外一块,再把原来的删掉,内存减半
l 标记压缩法
标记活跃对象,压缩到另一区域(java目前正在使用)
l 分代收集法
目前java采用的垃圾回收策略,将垃圾分为 年轻代,老年代,永久代
垃圾回收的方法
l System.gc();
l Runtime.gc();
(特别注意:垃圾回收机制是自动运行的,这两个方法就算调用也不一定会马上执行,要根据年轻代的情况)
l finalize()
这是Object的方法,当对象被清除时会调用此方法,也可以使用System.runFinalization()
来主动运行
(特别注意:这个方法每个对象只会被GC调用一次)
对象复活隐患以及内存泄漏
对象复活指的是,gc失去了内存对象的控制,原本应该被清扫的对象通过 finalize方法复活过来,造成这部分内存失控,也称为 内存泄漏

引用队列(补充)
引用队列介绍:ReferenceQueue
使用 软引用,弱引用,幻引用 引用和队列做关联的时候,垃圾回收机制回收该对象,引用队列中会多一个信息记录保存,研发者可以根据引用队列中是否有次信息来判断该对象是否被GC回收

浙公网安备 33010602011771号