Javaでのfinal、finally、finalizeの違い

1.概要

このチュートリアルでは、3つのJavaキーワードの概要を説明します。

これらのキーワードは互いに似ていますが、Javaではそれぞれ異なる意味を持ちます。それぞれの目的を学び、いくつかの例をいくつかのコードで説明します。

2. final キーワード

最初に final キーワードを見てみましょう。

  • final キーワードをクラス、メソッド、フィールド、変数、およびメソッドパラメータの宣言に適用できます。

  • ただし、それぞれに同じ効果はありません** 。

  • クラスを final にするということは、それを拡張することは不可能だということです。

クラス ** メソッドに final を追加することは、上書きすることが不可能になることを意味します

その方法 ** 最後に、 final をフィールド、変数、または変数の前に置きます。

パラメータは、いったん参照が割り当てられると変更できないことを意味します(ただし、参照が可変オブジェクトへのものである場合、内部状態は最終的であっても変更される可能性があります)。

final キーワードに関する詳細な記事はhttps://www.baeldung.com/java-final[here]にあります。

final キーワードがどのように機能するかをいくつかの例で見てみましょう。

2.1. final フィールド、パラメータ、および変数

2つの __int フィールド、1つの最終フィールド、および通常の非最終フィールドを含む Parent__クラスを作成しましょう。

public class Parent {

    int field1 = 1;
    final int field2 = 2;

    Parent() {
        field1 = 2;//OK
        field2 = 3;//Compilation error
    }

}

ご覧のとおり、コンパイラは field2 に新しい値を代入することを禁じています。

通常の引数と最後の引数を持つメソッドを追加しましょう。

    void method1(int arg1, final int arg2) {
        arg1 = 2;//OK
        arg2 = 3;//Compilation error
    }

フィールドと同様に、finalと宣言されているため、 arg2 に何かを割り当てることはできません。

これがローカル変数でどのように機能するかを説明するための2番目のメソッドを追加できます。

    void method2() {
        final int localVar = 2;//OK
        localVar = 3;//Compilation error
    }

驚くべきことは何も起こりませんが、コンパイラは最初の代入後に localVar に新しい値を代入させません。

2.2. final メソッド

method2 をfinalにして Parent のサブクラスを作成したとします。ここでは Child と言います。ここでは両方のスーパークラスメソッドをオーバーライドしようとします。

public class Child extends Parent {

    @Override
    void method1(int arg1, int arg2) {
       //OK
    }

    @Override
    final void method2() {
       //Compilation error
    }

}

ご覧のとおり、 method1() をオーバーライドしても問題ありませんが、 method2() をオーバーライドしようとするとコンパイルエラーが発生します。

2.3. 最終 クラス

そして最後に、 Child クラスをfinalにして、そのサブクラス GrandChild を作成してみましょう。

public final class Child extends Parent {
   //...
}
public class GrandChild extends Child {
   //Compilation error
}

もう一度、コンパイラは文句を言う。 Child クラスは最終的なものであり、したがって拡張することは不可能です。

3. __最終ブロック

finally ブロックは、 try/catch ステートメントで使用するオプションのブロックです。 ** このブロックには、例外がスローされるかどうかにかかわらず、 __try/catch __構造体の後に実行するコードを含めます。

finally ブロックが含まれていれば、 catch ブロックなしで try ブロックと一緒に使用することも可能です。その後、コードは try の後、または例外がスローされた後に実行されます。

Javaでの例外処理に関する詳細な記事があります。https://www.baeldung.com/java-exceptions[ここ]。

それでは、簡単な例で finally ブロックを説明しましょう。 try/catch/finally 構造を持つダミーの main() メソッドを作成します。

public static void main(String args[]) {
    try {
        System.out.println("Execute try block");
        throw new Exception();
    } catch (Exception e) {
        System.out.println("Execute catch block");
    } finally {
        System.out.println("Execute finally block");
    }
}

このコードを実行すると、次のように出力されます。

Execute try block
Execute catch block
Execute finally block

それでは、catchブロックを削除してメソッドを修正しましょう(そして throws Exception を署名に追加します):

public static void main(String args[]) throws Exception {
    try {
        System.out.println("Execute try block");
        throw new Exception();
    } finally {
        System.out.println("Execute finally block");
    }
}

出力は次のとおりです。

Execute try block
Execute finally block

throw new Exception() 命令を削除すると、出力は同じままであることがわかります。私たちの 最終的な ブロック実行は毎回行われます。

4. finalize メソッド

そして最後に、 finalize メソッドは、https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#finalize--[Objectクラス]で定義されているprotectedメソッドです。 ** もはや参照されておらず、ガベージコレクションの対象として選択されているオブジェクトに対して、 ガベージコレクタ によって呼び出されます。

他の最終的でないメソッドと同様に、このメソッドをオーバーライドして、 ガベージコレクタ によって収集されたときにオブジェクトが持つべき動作を定義することができます。

繰り返しますが、 finalize メソッドに関する詳細な記事はhttps://www.baeldung.com/java-finalize[ここ]にあります。

それがどのように機能するかの例を見てみましょう。 SVM.g )を使用して JVM ガベージコレクション__をトリガするように提案します。

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Execute finalize method");
        super.finalize();
    }
    public static void main(String[]args) throws Exception {
        FinalizeObject object = new FinalizeObject();
        object = null;
        System.gc();
        Thread.sleep(1000);
    }

この例では、オブジェクト内の finalize() メソッドをオーバーライドし、オブジェクトをインスタンス化し、作成された変数を null に設定することによって参照をすぐに削除する main() メソッドを作成します。

その後、 System.gc() を呼び出して ガベージコレクタ を実行し(少なくとも実行する予定です)、 ガベージコレクタ が呼び出す前に JVM がシャットダウンしないようにします。 finalize() メソッド)

このコード実行の出力は、次のようになります。

Execute finalize method

finalize() メソッドをオーバーライドすることは、その実行が JVM の手元にある ガベージコレクション に依存するため、悪い習慣と考えられています。 さらに、このメソッドはJava 9以降__非推奨となりました

5.まとめ

この記事では、Javaに似た3つのキーワード、 final、finally 、および finalize の違いについて簡単に説明しました。

記事の完全なコードが見つかります over on GitHub。