final修飾子
final修飾子 は「変数 を 定数 に変えたり、元のクラスやメソッドの機能を変えないための修飾子。」です。
具体的に言うと
といった使い方ができます。
固定にする理由
- 後から修正がかかった際、一か所を直せば済むから
- ソースの可読性が高まるから
- 変更されたくない値を変更されない様にするから
固定にするもの
メソッドのパラメーターや、メソッド のローカル変数 において、
条件分岐ごとの処理による値の書き換えの可能性が無いような場合は、 final で定義するほうがよいです。
具体的に「どんなものを定数にするか」ということですが、例を上げると
- 固定の文字列
- ダイアログなどのメッセージ
- サイトのURL
- 税率のような基本的に変わらない値
などがパッと思いつきました。
定数を定義する
「変数として扱う必要がない場合は、「 final 」をつける癖をつける。」
ソースを書いていて何度も使うものは変数にしますが、その中でも**「固定にするべき」**ものは、定数化しましょう。
- 変数は「値が変わるもの」
- 定数は「値が固定であるもの」
定数の命名規則 (SNAKE_CASE)
「SNAKE_CASE(スネークケース記法: すべて大文字とアンダースコア)でかくこと。」
定数は 変数特別するため、「 MY_NAME 」のような、すべて大文字で単語の書き方をしてください。
もちろん予約語はつかわないように。
暗黙的に「 public static finalで修飾される 」とセットで覚えておくといいかもしれない。
【定数を定義したクラス】
class ClassFinal {
// 変数に final を付与して 定数化。(大文字にすること)
public static final String MESSAGE = "定数です";
}
【定数を上書きしようとするクラス】
class FinalMain {
public static void main(String[] args) {
ClassFinal.MESSAGE = "定数を変えようとするとエラーになります";
}
}
【実行結果】
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
final フィールド ClassFinal.MESSAGE には代入できません
定数を定義する場所
個々のファイルへ定義するより、「CommonConstant.java」みたいな、定数専用のクラスを用意して、まとめて定義することが多い。
クラスにつける
クラスにfinal修飾子を付けると、
そのクラスは継承することが出来なくなり、コンパイルするとエラーとなります。
【finalにした親クラス】
final class ClassFinal {
String message = "finalクラスです";
public final void printMessage() {
System.out.println(this.message);
}
}
【継承しようとする子クラス】
public class ClassFinalChild extends ClassFinal {
//処理 ...
}
【呼び出そうとするクラス】
class FinalMain {
public static void main(String[] args) {
ClassFinalChild cfc = new ClassFinalChild();
}
}
【実行結果】
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
型 ClassFinalChild は final クラス ClassFinal をサブクラス化できません
メソッドにつける (オーバーライド)
メソッド につけると、そのメソッドは子クラスでのオーバーライドができなくなります。
【メソッドをfinalにした親クラス】
class ClassFinal {
String message = "finalクラスです";
//メソッドに final を付与
public final void printMessage() {
System.out.println(this.message);
}
}
【継承しようとする子クラス】
public class ClassFinalChild extends ClassFinal {
public void printMessage() {
System.out.println(this.message + "をオーバーライドします");
}
}
【呼び出そうとするクラス】
class FinalMain {
public static void main(String[] args) {
ClassFinalChild cfc = new ClassFinalChild();
}
}
【実行結果】
スレッド "main" での例外 java.lang.VerifyError: クラス practice_final_and_statc.ClassFinalChild は、最終メソッド practice_final_and_statc.ClassFinal.printMessage()V をオーバーライドします。