“横看成岭侧成峰,远近高低各不同。不识庐山真面目,只缘身在此山中。”

这首诗来自于宋朝苏轼《题西林壁》,它的意思是,庐山从正面看,它是一道道连绵起伏的山岭;从侧面看,它是一座巍然耸立的险峰,而从远处、近处、高处、低处看,庐山又呈现各种不同的样子。

我们之所以认不清庐山真正的面目,是因为人身处在庐山之中。诗的意思是指同一个事物在不同的角度和不同的时间看是不一样的,指出我们在看待或者观察问题时应当客观全面,如果主观片面的看问题,就会得出不正确的结论。

final、finally、finalize这三个关键字长得很像,对于Android初学者或者Java初学者来说容易混淆,有时分不清楚该怎样正确的使用它们,并且它们也经常是某些公司面试基础知识中的重点,所以我们有必要来专项学习一下它。今天我就来总结一下它们的定义,使用场景,区别等,争取把它们所有相关的知识点都一次性讲明白,使大家都能够很好的掌握它们。

1、关于final

final是Java中的一个修饰关键字,它可以用来修改类,方法和变量。

(1)、如果用它来修饰类,即类被声明为final,意味着这个类不能再派生出新的子类,不能作为父类被继承。例如,String、StringBuilder、StringBuffer、Math等类。它和abstract(抽象)是互斥的,用abstract修饰的类是必须要继承才能实例化对象的,因此一个类不能既被声明为 abstract,又被声明为final。

(2)、而用final修饰变量或方法时,可以保证变量或方法在使用中不被改变。

被final修饰的变量必须在声明时给定初值,而在以后的使用中只能读取,不可修改,场景包括形参,局部变量,成员变量等情况。如果修饰的是基本数据类型,则初始化之后变量的值不能被改变;如果修饰的变量是引用类型,那么它只能指向初始化时指向的那个对象,不能再指向别的对象,但是对象当中的内容是允许改变的。

(3)、被final修饰的方法也同样只能使用,不能被重载,但是子类可以使用或调用父类中final修饰的方法。

(4)、final有一个特殊的使用场景。

当方法内部声明的类或者方法内定义的匿名内部类,访问该方法内定义的局部变量时,该变量必须要用final修饰。因为当内部类或内部匿名类访问方法的局部变量时,相当于扩大了局部变量的作用域,如果局部变量不用 final 修饰,我们就可以在内部类中随意修改该局部变量值,而在该局部变量的作用域范围之外是可以看到这些修改后的值,这样将会出现安全问题,所以必须用final修饰,不允许内部类或内部匿名类修改变量的值。而方法内部类或内部匿名类在访问该方法所在的类的成员变量时,却可以不用final修饰。

如下所示,

public class TestFinal {
String str1 = "no need final";
//匿名内部类
public void testAnonyClass() {
final String str2 = "need final"; new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(str1);
System.out.println(str2); }
}).start();
} public void testInnerClass(){
final String str3 = "also need final";
//方法内部定义的内部类
class innerClass{
public void method1(){
System.out.println(str1);
System.out.println(str3);
}
}
}
}

如上所示str2在方法testAnonyClass中的匿名类中访问,它需要声明为final类型才可以,str3在方法testInnerClass中的内部类innerClass中访问,也同样需要声明为final。这两个方法中的内部类或内部匿名类在访问方法所在的类中的成员变量str1时,str1不需要声明为final。

2、关于finally

finally也是Java中的一个保留字,用在异常处理时,提供 finally代码块来执行最后的清除操作。

我们在写一段可能抛出异常的代码段时,如果我们希望捕获这个代码段中抛出的异常,那我们一般这样来写,

try {
//调用方法,期间可能抛出异常
//....
} catch (Exception e) {
e.printStackTrace();
} finally {
//可以进行一些清理
//....
}

如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后最终控制会进入 finally代码块。

finally语句不会被执行的唯一情况是:先执行了用于终止程序的System.exit()方法,这个时候不会走到finally语句中,或者如果在执行过程中突然断电了,这时所有进程都会终止,也不会执行finally语句。

大家看一下如下demo,猜一猜打印的结果是什么?

public class TestFinally{
public int testFinally(){
try{
System.out.println("-----try-----");
return 1;
}finally{
System.out.println("-----finally-----");
return 2 ;
}
}
public static void main(String[]args){
TestFinally te= new TestFinally();
int t = te.testFinally();
System.out.println(t);
}
}

这里有两个return,按正常逻辑在try中调用return后,方法就返回了,但是因为下面有finally语句,并且其中也有一个return,所以最终应该返回finally语句中return对应的结果。

以上程序运行结果如下所示,

-----try-----

-----finally-----

2

如果注释掉finally语句中return,返回结果如下所示,

-----try-----

-----finally-----

1

可见finally中的语句永远都是要执行的。

3、关于finalize

finalize是Java中的一个方法名,它在Object类中定义,因此所有的类都继承了它。finalize() 方法的作用是在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。垃圾收集器在确定这个对象没有被引用时将调用此对象的finalize()方法,或者说finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。子类可以覆盖finalize() 方法从而整理自己定义的各类资源,或者执行资源清理工作。

使用场景,当销毁一个对象时,需要执行一些额外操作。例如,如果一个对象创建了一些非Java 资源,如文件句柄,window 字符字体或者数据库cursor等,这时你在这个对象被销毁前,要保证这些资源被安全释放。那如何保证呢?Java提供了一种收尾(finalization)机制,可以通过重写finalize() 方法来实现这种机制,在这种机制或者finalize() 方法中,可以将对象在进行垃圾回收前释放之前创建的其它资源。

在finalize ( )方法中,你要指定这个对象被撤消前必须执行的操作。系统的垃圾回收会周期性地运行,将由JVM的垃圾回收机制来控制,它会检查此对象是不是不再被运行状态引用或间接地引用。如果没有被引用,将会释放此对象,对应的inalize( ) 方法就会执行。

finalize()方法定义如下所示:

protected void finalize( )
{
// finalization code here
}

但是,finalize( )并不确保一个对象超出了它的作用域时就会执行,也就是说你不可能知道何时,甚至是否finalize( ) 被调用,因为这完全取决于系统的垃圾回收机制。所以,释放对象所创建的资源最好使用其它方法来实现,而不能仅仅依靠finalize( ) 来完成程序的资源释放工作。

finalize()在什么场景使用呢?

有三种情况

(1)、对象没有了直接和间接引用,垃圾回收器(garbage colector)决定回收某对象时,比如运行System.gc()的时候。

(2)、程序退出时为对象调用一次finalize方法。

(3)、显式的调用finalize方法。`

4、总结

由以上介绍,我们应该对final、finally、finalize有所了解了。对于它们的使用,还需要我们在工作中多摸索和多实践,这样才会理解的更加深刻,运用起来才会得心应手,才不会对它们产生混淆。



本公众号将以推送Android各种技术干货或碎片化知识,以及整理老司机日常工作中踩过的坑涉及到的经验知识为主,也会不定期将正在学习使用的新技术总结出来进行分享。每天一点干货小知识把你的碎片时间充分利用起来。

知识点干货--讲一讲final、finally、finalize的区别的更多相关文章

  1. Android源码中final关键字的用法及final,finally,finalize的区别

    Android开发的学习流程 final,finally,finalize的区别 Android的发展越来越快,Android开发人员越来越多,当两种情况碰撞,在诸多开发者中跟紧Android步伐脱颖 ...

  2. 【Java面试题系列】:Java中final finally finalize的区别

    本篇为[Java面试题系列]第三篇,文中如有错误,欢迎指正. 第一篇链接:[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 第二篇链接:[Java面试题系列]:Java基础知识常见面试题 ...

  3. 一、基础篇--1.1Java基础-final, finally, finalize 的区别

    final, finally, finalize 首先,这三个关键字没什么关联,只是放在一起比较像,用法用处完全不同. final: final关键字可以用来修饰类.方法.变量(成员变量和局部变量), ...

  4. final, finally, finalize的区别

    1.final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承. 内部类要访问局部变量,局部变量必须定义成final类型 2.finally是异常处理语句结构的一部分,表示总是执 ...

  5. java中的final, finally, finalize的区别

    final修饰符(关键字),如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为abstract的,又被声明为final的.将变量或方法声明为fin ...

  6. final, finally, finalize 的区别

    1.final 用于声明属性, 方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.内部类要访问局部变量, 局部变量必须定义成 final 类型, 例如, 一段代码…… 2.finally ...

  7. 谈谈final, finally, finalize的区别

    final 修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为fi ...

  8. 2018.5.7每天一题面试题----final, finally, finalize 的区别

    1.final修饰符(关键字).被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承. 因此一个类不能既被abstract声明,又被final声明.将变量或方法声明为final ...

  9. 请解释final finally finalize的区别

    final  关键字 ,可以定义不能被继承的父类.定义不能被重写的方法,常量 finally   关键字, 异常处理的统一出口 不管是否有异常都执行 finalize   方法(protected   ...

  10. final, finally, finalize的区别?

    final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承.内部类要访问局部变量,局部变量必须定义成final类型.finally是异常处理语句结构的一部分,表示总是执行.fin ...

随机推荐

  1. mybatis if条件查询 及<号的问题

    摘录自:http://flt95.blog.163.com/blog/static/12736128920136185841551/ <if test="p=='1'"> ...

  2. 如何安装 Composer

    下载 Composer 安装前请务必确保已经正确安装了 PHP.打开命令行窗口并执行 php -v 查看是否正确输出版本号. 打开命令行并依次执行下列命令安装最新版本的 Composer: php - ...

  3. shell 实现主板测试

    初接触shell,只能需要用到什么功能现学先用了.本文总结一下完成测试程序当中遇到的技巧和问题. 01. 变量生存期的问题,在函数中的变量无法在其他地方使用,在函数中只能使用在函数前定义的全局变量: ...

  4. 2017-06-23(chmod whoami chown)

    文件权限设定 chmod u-x newfile chmod u-x,g+w newfile chmod a=rwx newfile [mode=421] r = 4 , w=2, x=1 chmod ...

  5. 2017-06-19 (cp mkdir rm 运行级别及修改)

    mkdir 用于创建目录 mkdir  -p  递归创建目录 mkdir -p /linux/linux rm 用于删除文件与目录 rm -r  删除目录 -f  强制删除   (一般情况下 rf 组 ...

  6. python_如何快速找打字典中公共key

    场景实例: 西班牙足球联赛,每轮球员进球统计: 第一轮:{'1':1,'2':4,'5':2,'7':3} 第一轮:{'2':1,'5':4,'6':2,'3':3} 第一轮:{'1':1,'4':4 ...

  7. JS题目

    1.请你谈谈Cookie的弊端 cookie虽然在持久保存客户端数据提供了方便,分担了服务器存储的负担,但还是有很多局限性的. 第一:每个特定的域名下最多生成20个cookie 1.IE6或更低版本最 ...

  8. SpringBoot整合Redis、ApachSolr和SpringSession

    SpringBoot整合Redis.ApachSolr和SpringSession 一.简介 SpringBoot自从问世以来,以其方便的配置受到了广大开发者的青睐.它提供了各种starter简化很多 ...

  9. 树莓派小车By 树莓派爱好者ITJoker(通过python socket通信实现树莓派视频小车)(一)

    本文由树莓派爱好者ITJoker 编辑,转载请注明出处.本人也有新浪博客同样是树莓派爱好者ITJoker 所需材料:树莓派2B或者2B以上,L2985n驱动板,若干排线,电池及电池盒,usb无线网卡( ...

  10. ABP官方文档翻译 3.6 工作单元

    工作单元 介绍 ABP中的连接和事务管理 传统的工作单元方法 控制工作单元 UnitOfWork特性 IUnitOfWorkManager 工作单元详情 禁用工作单元 无事务工作单元 一个工作单元方法 ...