final, finally, finalize 的区别

文章目录

      • 1 final 用法
        • 1.1 final 修饰类
        • 1.2 final 修饰方法
        • 1.3 final 修饰变量
      • 2 finally 用法
        • 2.1 finally 语句块执行时机
        • 2.2 finally 不执行的情况
      • 3 finalize 用法

虽然这个三个单词在 Java 中都存在,但是并没太多关联:
1)final:java 中的关键字,修饰符、方法、变量。
2)finally:java 的一种异常处理机制。
3)finalize:Java中的一个方法名。
具体用法说明如下:

1 final 用法

在 java 中,final 可以用来修饰类,方法和变量(成员变量或局部变量)。
下面将对其详细介绍。

1.1 final 修饰类

如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此:

  • 当我们需要让一个类永远不被继承,此时就可以用 final 修饰。
  • 一个类不能同时被声明为 abstract 抽象类的和 final 的类。

注意:
final 类中所有的成员方法都会隐式的定义为 final 方法。

1.2 final 修饰方法

final 方法意味着“最后的、最终的”含义,即被声明 final 的方法只能使用,不能重载。

使用 final 方法的原因主要有两个:

  • 把方法锁定,以防止继承类对其进行更改。
  • 效率,在早期的java版本中,会将 final 方法转为内嵌调用。但若方法过于庞大,可能在性能上不会有多大提升。因此在最近版本中,不需要 final 方法进行这些优化了。

demo 示例:

class A{
    private final void getName(){
        System.out.println("A.getName()...");
    }
}
class B extends A{
    public void getName(){
        System.out.println("B.getName()...");
    }

    public static void main(String[]args){
        B b = new B();
        b.getName();
    }
}
  • 结果:
B.getName()...

1.3 final 修饰变量

final 成员变量表示常量,只能被赋值一次,赋值后其值不再改变。

final 修饰成员变量时,必须要显示初始化。这里有两种初始化方式:一种是在变量声明的时候初始化;第二种方法是在这个变量所在的类的所有的构造函数中对这个变量赋初值。

如果将变量或者方法声明为 final,可以保证它们在使用中不被改变。在并发编程中,将公共变量设置为 final 是最简单的并发安全实现方法。

2 finally 用法

finally 是对 Java 异常处理模型的最佳补充。finally 结构使代码总会执行,而不管有无异常发生。

常使用 finally关闭数据库连接、关闭流等释放资源的操作。防止程序发生异常退出而没有释放相应的资源。

2.1 finally 语句块执行时机

  • 代码示例:
@Test
public void testFinally1() {
    System.out.println("结果1:"+a1(null));
    System.out.println("-------------");
    System.out.println("结果2:"+a1(5));
    System.out.println("-------------");
    System.out.println("结果3:"+a1(3));
}

public static int a1(Integer aaa) {
    try {
        if (aaa.equals(5)) {
            System.out.println("55555");
            return 5;
        }
        System.out.println("11111");
        return 1;
    }catch (Exception e) {
        System.out.println("22222");
        return 2;
    }finally {
        System.out.println("33333");
        return 3;
    }
}
  • 输出结果:
22222
33333
结果1:3
-------------
55555
33333
结果2:3
-------------
11111
33333
结果3:3
  • 结论:
    从运行结果来看,每次 return 的结果都是3(即finally语句),仿佛其他return语句被屏蔽掉了。

    事实也确实如此,因为 finally 用法特殊,所以会撤销之前的 return 语句,继续执行最后的 finally 块中的代码。

2.2 finally 不执行的情况

  • 代码示例:
@Test
public void test2() {
    System.out.println(a2(1));
    System.out.println("-------------");
    System.out.println(a2(9));
    System.out.println("-------------");
    System.out.println(a2(6));
}

public static int a2(Integer i) {
    System.out.println("start...");
    if (i == 1) {return 0;}
    System.out.println("before try block");
    try {
        System.out.println("try block");
        if (i == 6) {
            System.exit(0);
        }
        return i;
    }finally {
        System.out.println("finally block");
    }
}
  • 输出结果:
start...
0
-------------
start...
before try block
try block
finally block
9
-------------
start...
before try block
try block
  • 结论:
  1. try 语句块中调用 System.exit(0) 方法时,虚拟机会退出,中断程序,finally 语句块不会执行。
  2. 只有 try 语句块执行了,且程序未中断,finally 语句块才会执行。

3 finalize 用法

finalize() 是在 java.lang.Object 里定义的,也就是说每一个对象都有这么个方法。

这个方法在 gc 启动,该对象被回收的时候被调用。其实 gc 可以回收大部分的对象(凡是 new 出来的对象,gc 都能搞定,一般情况下我们又不会用 new 以外的方式去创建对象),所以一般是不需要程序员去实现 finalize 的。

一个对象的 finalize() 方法只会被调用一次,而且 finalize() 被调用不意味着 gc 会立即回收该对象,所以有可能调用 finalize() 后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用 finalize(),产生问题。

所以,推荐不要使用 finalize() 方法,它跟析构函数不一样。

代码示例:

class C {
    public static void main(String[] args) {
        new C();
        System.gc();
    }

    protected void finalize() throws Throwable {
        System.out.println("finalize execute ... ");
    }
}

输出结果:
finalize execute …

PS:如有疑问,欢迎指正。如果觉得不错,点赞支持一下。
------ 更多内容欢迎关注 ----------
更多内容欢迎关注

你可能感兴趣的:(java,面试,Java面试总结,java,面试)