final、finally、finalize

基础:

  1. final可以用来修饰类,方法、变量,分别有不同的意义,修饰class时,该class不能被继承,修饰方法时,该方法不能被重写,修饰基本变量时,该变量不可变,修饰引用类型时,引用不可以被赋值,但引用的对象的行为不受影响;
  2. finally,finally是java保证某些关键代码一定会被执行的一种手段,配合try或者try-catch语句一起使用;
  3. finalize是Object类的一个方法,设计之初是想 对象被垃圾回收之前 做某些资源回收工作,因为其机制问题,已经不推荐使用,甚至再JDK9中明确标记未deprecated;

扩展:
final:
4. final关键字可提现设计者的设计意图、代码语义,使用final修饰方法或者类可以明确的告诉别人,这些是不允许修改的;某些时候是必须的选择, 如基础类库很多类都申明为final的,可有效避免API使用者更改平台的基本功能,是保证平台安全的必要手段;
5. 在多线程环境中,不可变是一个非常棒的选择,这意味着不需要额外的同步开销;基本类型仅用final修饰即可达到目的;如果是引用对象的,final修饰只能保证引用不被更改,无法限制对象的行为,如果是要实现对象类型的不可变效果,还需要对象支持;
6. 首先将成员变量申明为私有的,避免外部访问者直接更改数据;并且不要实现set方法;
7. 其次,使用final修饰class,避免使用者通过继承来绕开限制;
8. 最后,成员变量使用深度拷贝来初始化,避免外部程序意外修改数据;

finally:
9. finally作为一段代码一定会运行的手段,其实并不绝对,如:

try{
	System.exit(0);
} finally{
	System.out.println("finally");
}

代码中finally是不会被打印的,这句代码不会运行;因为遇到System.exit(0)时候,java虚拟机就被关闭了,程序就已经退出了;
10. 上述例子如果将System.exit(0)该为return会如何呢?毕竟return也以为着函数结束并返回;结果是程序不会中止,finally代码块的内容依然会被执行,从JDK8将代码编译并反编译为的字节码来看,编译器是去掉了try中的return的实际操作,仅仅只是将返回值赋值给一个变量(放入栈顶?),然后再finally代码块执行之后再真正执行return操作;
11. 那么如果在try finally代码块中如果同时使用了return语句会如何呢?try中代码运行情况与第10点描述一直,然后会将finally中的return值赋值给一个变量,然后返回,至于这个变量与第10点中提到的变量是否是同一个这个问题,没有仔细研究;但可以肯定的是try中的返回值丢失了,函数将只会返回finally中的返回值;
12. 如果try中抛出异常,那么finally也会执行,java是通过为finally生成一个或者多个异常处理器来实现的,监控try-catch代码段的运行,捕捉任何Throwable来实现的,运行完finally中的代码后重新抛出捕获的异常;这就意味着try-catch-finally代码段除了catch声明的异常处理器外,finally也会生成异常处理器;
13. 第12点中,finally生成的异常处理器优先级低于catch异常处理器,如果被监控的代码段抛出异常,只有catch生成的异常处理器没有匹配的类型的时候,finally生成的异常处理器才会捕获异常并在执行完finally代码块后重新抛出异常;
14. 如果catch中也触发了异常会如何?因为catch生成的异常处理器仅监控try代码段,并不会监控catch代码段,所以catch代码段若抛出异常,无论catch列表中是否有对应异常,都不会被捕获,此时异常会被finally捕获,然后被重新抛出,那么此时重新抛出的异常是catch代码段中触发的异常,try中的异常信息将会丢失,无法catch代码段在抛出新异常之前是否对该异常做了充分的处理;
15. 第14点描述的异常信息丢失可通过JDK7引入的supressed exception来解决,他允许将一个异常布于另一个异常之上,但语法晦涩,推荐使用
try with resources 语法,它会自动使用supressed exception,可有效避免原有异常信息的丢失,代码也会精简一些;
16. 如果finally中也出现了异常呢?这时候JVM没有更好的办法处理,只能中断当前finally代码块,往外抛出异常;此处抛出的应该是finally触发的异常,至于是否附带了原来异常的信息,还需要进一步关注;

finalize:
finalize函数被设计为在对象被垃圾回收前运行,用其实现资源回收有很多问题,finalize中代码是否被执行,何时被执行以及执行结果是否符合预期这些都无法得到保证,所以使用finalize实现资源回收不是个好主意:
17. 实现了非空的finalize的对象,需要在垃圾回收前需要先调用finalize方法,会拖慢垃圾回收速度,可能导致对象经过多个垃圾收集周期才能被回收,成为快速回收的阻碍者;
18. finalize由JVM线程调用执行,如果出现异常,JVM没有办法处理,只能使用try catch Throwable掩盖问题,Throwable被生吞了,即finalize过程中出现任何问题,我们得不到任何有效信息;
19. finalize无法保证资源及时回收,finalize运行的时间不确定,这意味着某些资源已经不再使用了确得不到释放,这将极大的占用系统资源,出现明明资源还有闲置,但却申请不到资源的情况;
20. finalize由JVM线程调用,若线程出现死锁,所有实现了finalize的无用对象都因无法执行finalize函数而无法得到回收,后果非常严重;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值