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

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

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

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. Linux IO时事检测工具iostat

    Linux IO时事检测工具iostat iostat命令用于检测linux系统io设备的负载情况,运行iostat将显示自上次运行该命令以后的统计信息.用户可以通过指定统计的次数和时间来获得所需的统 ...

  2. vuejs axios安装配置与使用

    1.安装服务 npm install --save axios vue-axios 2.在main.js import axios from 'axios' import VueAxios from ...

  3. DOS、Mac 和 Unix 文件格式[转]

    DOS.Mac 和 Unix 文件格式 相信很多朋友都碰到过这三种文件格式的互换问题,今日又碰到这个问题,忽然想寻根问底,于是整理了本文档. 文件格式区别   我们先看看这三个家伙有啥区别.很久以前, ...

  4. scrapy_xpath

    什么是xpath? 路径表达式 在xml和html中进行导航 包含标准函数库 遵循w3c标准 xpth节点关系是什么? 父节点 子节点 兄弟节点 先辈节点 后代节点 xpth语法 a         ...

  5. vs2005配置OpenCv2.3.1

    编译OpenCv 1 用CMake导出VC++项目文件 运行cmake-gui,设置where is the source code路径为OpenCV安装路径(本文档假定安装位置为:c:\OpenCV ...

  6. Git初入

    Git记录 使用git 也有一段时间了, git的入门级了解也就不再多说, 但平常使用中, 仍然会遇到很多问题, 在此记录一二. 在查资料的过程中, 发现了两个比较好的资料: 特别是第二个, 相当详细 ...

  7. MySQL中union和order by一起使用的方法

    MySQL中union和order by是可以一起使用的,但是在使用中需要注意一些小问题,下面通过例子来说明.首先看下面的t1表. 1.如果直接用如下sql语句是会报错:Incorrect usage ...

  8. input标签的美化

    css input checkbox和radio样式美化:http://www.haorooms.com/post/css_mh_ck_radio 自定义 css checkbox 样式  :http ...

  9. CentOS7修改主机名(hostname)

    Linux中的hostname在大多数应用中至为重要,例如有些应用强制使用主机名称而不能使用IP地址,如果默认主机名称都为localhost.localdomain 的话那一定会出现问题,而且看起来也 ...

  10. Ajax发送数据