关于final、finally、finalize的区别

1.final 的作用

Java中的关键字,主要用来修饰Java类、Java方法以及Java变量(成员变量或局部变量)

  • 当一个类被声明为final,意味着他不能再派生出新的子类,不能作为父类被继承。例如Java的String类就是一个被final修饰的类,此类不能被任何类所继承。
  • 若将变量和方法声明为final,可以保证他们在使用中不被改变。
  • 其初始化的可以在两个地方:
    一是其定义处,也就是说在final变量定义时直接给其赋值,
    二是在构造函数中。被声明为final的方法只能使用,不能重写。
public class FinalTest1 {  
    //-----------------成员变量------------------//  
    //初始化方式一,在定义变量时直接赋值  
    private final int i = 3;  

    //初始化方式二,声明完变量后在构造方法中为其赋值  
    //如果采用用这种方式,那么每个构造方法中都要有j赋值的语句  
    private final int j;  

    public FinalTest1() {  
        j = 3;  
    }  

    //如果取消该构造方法的注释,程序就会报错,因此它没有为j赋值  
    /*public FinalTest1(String str) { 

    }*/  

    //为了方便我们可以这样写  
    public FinalTest1(String str) {  
        this();  
    }  

    //下面的代码同样会报错,因为对j重复赋值  
    /*public FinalTest1(String str1, String str2) { 
        this(); 
        j = 3; 
    }*/  


    //初始化方式三,声明完变量后在构造代码块中为其赋值  
    //如果采用此方式,就不能在构造方法中再次为其赋值  
    //构造代码块中的代码会在构造函数之前执行,如果在构造函数中再次赋值,  
    //就会造成final变量的重复赋值  
    private final int k;  

    {  
        k = 4;  
    }  

    //-----------------类变量(静态变量)------------------//  
    //初始化方式一,在定义类变量时直接赋值  
    public final static int p = 3;  

    //初始化方式二,在静态代码块中赋值  
    //成员变量可以在构造函数中赋值,但是类变量却不可以。  
    //因此成员变量属于对象独有,每个对象创建时只会调用一次构造函数,  
    //因此可以保证该成员变量只被初始化一次;  
    //而类变量是该类的所有对象共有,每个对象创建时都会对该变量赋值  
    //这样就会造成变量的重复赋值。  
    public final static int q;  

    static {  
        q = 3;  
    }  
}  

2.finally 的作用

finally是Java中异常捕捉try-catch-finally块中的一部分,有时可以省略,主要的作用是处理一些后续的操作比如说是连接的管理以及流的关闭等一系列操作。包含在finally块中的代码不管异常是否发生都会执行。(但是当try或者catch代码块中出现System.exit(0)或系统被强制中断时finally是不会被执行的)
当try块、catch块和finally中同时存在return时,程序会执行finally块的中的return。

关于finally的详细介绍请访问:
https://www.ibm.com/developerworks/cn/java/j-lo-finally/

3.finalize 的作用

这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前被自动调用的。
垃圾收集器只知道释放那些由new分配的内存,所以不知道如何释放对象的“特殊”内存。为解决这个问题,Java提供了一个名为finalize()的方法,它的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作(如关闭流等操作)。但JVM(Java虚拟机)不保证此方法总被调用。
Finalize 操作具有下列限制:
垃圾回收过程中执行终结器的准确时间是不确定的。不保证资源在任何特定的时间都能释放,除非调用 Close 方法或 Dispose 方法。
即使一个对象引用另一个对象,也不能保证两个对象的终结器以任何特定的顺序运行。即,如果对象 A 具有对对象 B 的引用,并且两者都有终结器,则当对象 A 的终结器启动时,对象 B 可能已经终结了。
运行终结器的线程是未指定的。
在下面的异常情况下,Finalize 方法可能不会运行完成或可能根本不运行:
另一个终结器无限期地阻止(进入无限循环,试图获取永远无法获取的锁,诸如此类)。由于运行时试图运行终结器来完成,所以如果一个终结器无限期地阻止,则可能不会调用其他终结器。
进程终止,但不给运行时提供清理的机会。在这种情况下,运行时的第一个进程终止通知是 DLL_PROCESS_DETACH 通知。
在关闭过程中,只有当可终结对象的数目继续减少时,运行时才继续 Finalize 对象。
如果 FinalizeFinalize 的重写引发异常,并且运行库并非寄宿在重写默认策略的应用程序中,则运行库将终止进程,并且不执行任何活动的 try-finally 块或终结器。如果终结器无法释放或销毁资源,此行为可以确保进程完整性。
给实现者的说明 默认情况下,Object.Finalize 不执行任何操作。只有在必要时才必须由派生类重写它,因为如果必须运行 Finalize 操作,垃圾回收过程中的回收往往需要长得多的时间。 如果 Object 保存了对任何资源的引用,则 Finalize 必须由派生类重写,以便在垃圾回收过程中,在放弃 Object 之前释放这些资源。 当类型使用文件句柄或数据库连接这类在回收使用托管对象时必须释放的非托管资源时,该类型必须实现 Finalize。有关辅助和具有更多控制的资源处置方式,请参见 IDisposable 接口。 Finalize 可以采取任何操作,包括在垃圾回收过程中清理了对象后使对象复活(即,使对象再次可访问)。但是,对象只能复活一次;在垃圾回收过程中,不能对复活对象调用 Finalize

你可能感兴趣的:(Java)