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

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

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

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. Cannot complete the install because one or more required items could not be found

    弄了一天的subclipse也没装上,郁闷~~~~~~~~ 无论采用本地安装还是站点安装都不行,在安装的时候显示错误: Cannot complete the install because one  ...

  2. 【WebApi系列】详解WebApi如何传递参数

    WebApi系列文章 [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi参数的传递 [04]详解WebApi测试和PostMan [05]浅谈W ...

  3. javascript函数之arguments

    function foo(x,y,z){ console.info (arguments.length); //2 实际的参数个数 console.info(arguments[0]); //传入的第 ...

  4. centos下配置sftp且限制用户访问目录[转]

    第一步:创建sftp服务用户组,创建sftp服务根目录 groupadd sftp #此目录及上级目录的所有者(owner)必须为root,权限不高于755,此目录的组最好设定为sftp mkdir ...

  5. BFC(块级格式上下文)

    BFC的生成 满足下列css声明之一的元素便会生成BFC 根元素 float的值不为none overflow的值不为visible display的值为inline-block.table-cell ...

  6. 关于awk的范围模式功能问题

    关于awk的范围模式功能问题 man awk中这样写到 The pattern1, pattern2 form of an expression is called a range pattern. ...

  7. 【转】TCHAR

    TCHAR 就是当你的字符设置为什么就是什么例如: 当程序编译为    ANSI,    TCHAR 相当于 CHAR当程序编译为 UNICODE, TCHAR 相当于WCHAR char       ...

  8. 常用Nagios配置命令

    cd /usr/local/nagios/etc vim nagios.cfg /usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios ...

  9. ABP框架源码学习之修改默认数据库表前缀或表名称

    ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 namespace Abp.Zero.EntityFramework { /// <summary> /// Extension ...

  10. 同一台机器上多个tomcat启动造成的内存溢出问题的解决方法。

    加下面这句话就行了,我是WIN10+双tomcat+nginx(本地站点),无压力.在编译器的vm option里面加哦. -server -Xms512m -Xmx1024m -XX:PermSiz ...