我是靠谱客的博主 无情鸡翅,最近开发中收集的这篇文章主要介绍Java中final、finally和finalize的区别,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

简介:

“final、finally和finalize有什么区别?”, 这是一道再经典不过的面试题了,我们在各个公司的面试题中几乎都能看到它的身影。final、finally和finalize虽然看起来很像,含义也差不多(字根都是final),但是它们的用法是不同的。本节主要来讨论一下它们在实际场景中的运用。

final用法说明:

是java关键字之一,用于修饰类或者方法,或者变量,可以和static共存。
被fianl修饰的这些类,方法,变量都不能再被修改。对于类,不能再被继承;对于方法,不能被重写;对于基本类型的变量,不能修改其值(其实就是常量);

对于引用类型(即final修饰的是一个对象的情形),就表示这个变量被赋予的引用是不可变的,注意,不可改变的只是这个变量所保存的引用,并不是这个引用所指向的对象。

一个类不能既被abstract声明,又被final声明,这是因为被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承,这和abstract正好是互斥的。

被final修饰的变量必须被初始化。初始化方式:
在定义的时候初始化。
final变量可以在初始化块中初始化,不可以在静态初始化块中初始化。
静态final变量可以在静态初始化块中初始化,不可以在初始化块中初始化。
final变量还可以在类的构造器中初始化,但是静态final变量不可以。

final用来修饰一个变量:

程序举例:

package demo.test.my;

public class BydCar {

    // 非静态final变量在定义时初始化
    public final String tagName = "BydCar";

    //非静态final变量可以在静态初始化块中初始化
    public final int tagId;
    // 在初始化块中初始化
    {
        tagId = 10000;
    }

    // 非静态final变量不能在静态初始化块中初始化
    // public final int C;
    // static {
    // C = 30;
    // }

    // 静态常量,在定义时初始化
    public static final float Min_Value = 0;

    public static final float Max_Value;
    // 静态常量,在静态初始化块中初始化
    static {
        Max_Value = 200.0f;
    }

    // 静态变量不能在初始化块中初始化
    // public static final int Max_Value;
    // {
    // Max_Value = 200.0f;
    // }

    //非静态final变量可以在构造器中初始化
    public final int code;

    // 静态final变量不可以在构造器中初始化
    // public static final int code;

    // 在构造器中初始化
    public BydCar() {
        code = 666666; //非静态final变量可以在构造器中初始化
        // 静态final变量不可以在构造器中初始化
        // code = 777777;

        // 给final的变量第二次赋值时,编译会报错
         //code = 888888;   //Variable 'G' might already have been assigned to
    }

    // final变量未被初始化,编译时就会报错
    //public final int I;   //编译错误:Variable 'I' might not have been initialized

    // 静态final变量未被初始化,编译时就会报错
    //public static final int STATIC_J;  //编译错误: Variable 'STATIC_J' might not have been initialized
}

运行上面的代码之后出了可以发现final变量(常量)和静态final变量(静态常量)未被初始化时,编译会报错;
另外还可以发现,静态final变量可以在构造器中初始化,却不可以在初始化块中初始化。 

final用来修饰一个方法:

程序举例:

BaseClass.java:

package demo.test.my;

public class BaseClass {
    //
    public final void fun() {
        System.out.println("[BaseClass] fun be call!");
    }
}

SubClass.java:继承自BaseClass

package demo.test.my;

public class SubClass extends BaseClass {
    /**
     * 子类无法重写(override)父类的final方法fun,否则编译时会报错:
     * 'fun()' cannot override 'fun()' in 'demo.test.my.BaseClass'; overridden method is final
     */
//     public void fun() {
//         System.out.println("[SubClass]子类--重写final方法");
//     }

    public static void main(String[] args) {
        SubClass sc = new SubClass();
        sc.fun(); //调用弗雷的fun
    }
}

运行结果:

[BaseClass] fun be call!
 

这里需要特殊说明的是,具有private访问权限的方法也可以增加final修饰,但是由于子类无法继承private方法,因此也无法重写它。

finally的用法:

finally是java的关键字,用在try-catch-finally,最终被执行的代码放在finally语句块中。

注意,return、continue和break都无法阻止finally语句块的执行。

finally的代码示例:

package demo.test.my;

public final class F0Car {
    public static void main(String[] args) {
        try {
            throw new NullPointerException();
        } catch (NullPointerException e) {
            System.out.println("程序抛出了异常");
            return;
        } finally {
            System.out.println("执行了finally语句块");
        }
    }
}

运行结果:

程序抛出了异常
执行了finally语句块

finalize的用法:

finalize不是java关键字,而是一个方法,属于java.lang.Object类的一个方法,它的定义如下:

protected void finalize() throws Throwable { }

finalize()方法是在GC清理它所从属的对象时被JVM自动调用的,如果执行它的过程中抛出了无法捕获的异常(uncaught exception),GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。

finalize的代码示例:

package demo.test.my;

public final class F0Car {
    // 重写finalize()方法
    protected void finalize() throws Throwable {
        System.out.println("F0Car::finalize()"); //输出:F0Car::finalize()
    }

    public static void main(String[] args) {
        F0Car car = new F0Car();
        car = null;
        System.gc();
    }
}

运行结果:

F0Car::finalize()

 分析:

程序调用了java.lang.System类的gc()方法,引起GC的执行,GC在清理ft对象时调用了它的finalize()方法,因此才有了上面的输出结果。调用System.gc()等同于调用下面这行代码:

Runtime.getRuntime().gc();

调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC的启动并不是一定的,这由JAVA虚拟机来决定。


最后

以上就是无情鸡翅为你收集整理的Java中final、finally和finalize的区别的全部内容,希望文章能够帮你解决Java中final、finally和finalize的区别所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部