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回收

 

posted @ 2021-07-19 09:07  二娃千里眼  阅读(133)  评论(0)    收藏  举报