検索

キーワード


【Java】final 修飾子の使い方は?変数やメソッドなどでの利用方法まとめ

  • 公開日:2020-09-10 09:28:43
  • 最終更新日:2021-01-26 09:17:34
【Java】final 修飾子の使い方は?変数やメソッドなどでの利用方法まとめ

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私からアウトプットの意味も込めて、

final 修飾子について紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:インターフェースの紹介 / 継承とオーバーライドの紹介 / 変数の紹介 / メソッドの紹介 / コレクションの紹介 / クラスの紹介 / 配列の紹介 / インスタンスの紹介 / 抽象クラスの紹介

final 修飾子の使い方まとめ

final 修飾子はデータの変更や継承、オーバーライド、参照先の変更などを阻止する役割を持ちます。

プログラマーが意図的に変更の阻止を行うことで、意図しない変更を未然に防いだり、

変更に対するセキュリティを強めることが可能となります。

ここでは変数やメソッド、クラスなどさまざまな場所に登場する、

final 修飾子について紹介させていただきます。


final 修飾子とは?

final 修飾子の付いたものは「最終」の意味を持ち、

強制的にそれ以降の変更ができないようにすることができます。

そのため final 修飾子を付ける目的は主に「内容が変更されると困るもの」や「扱いが複雑なもの」などです。

また「それ以降変更がないもの」にも目印として付けられることもあります。


変更を不可にする final 修飾子は付与するものによって、その働きがそれぞれ異なります。

final 修飾子の書き方も含めて変数、メソッド、クラス、配列、コレクションでどのような働きをするか

一つずつ確認していきましょう。


final 修飾子がついた変数の種類

変数が値を受け取る回数を1回に限定することができます。

そのため変数が値を1度受け取った後に再代入を行おうとするとエラーが返ってきます。

また、final 修飾子付きの変数は必ず値を保持しなければならないという条件があります。


変数にはローカル変数やインスタンス変数、グローバル変数があるため、

final 修飾子を付けた際のそれぞれのサンプルコードを見てみましょう。

ちなみに final 修飾子の付いた変数は、値が固定されるため定数扱いとなります。


ローカル変数の final 修飾子

ローカル変数に final 修飾子を付けた場合は、上記で紹介した通り再代入が不可となります。

メソッド内で使う変数を固定したいときなどに final 修飾子を付けます。


◆ローカル変数の final 修飾子例

public class FinalTest {

	public void number() {
		final int num = 1; // final なローカル変数 num の初期値を 1 にする
		num = 2; // コンパイルエラー:ローカル変数 num に再代入は不可
	}
}


引数に final 修飾子を付けた場合は、引数が値を受け取った以降の再代入ができません。

public class FinalTest {

	public void number(final int num) {
		num = 1; // 引数に final が付いているため再代入ができない
	}
}


インスタンス変数の final 修飾子

インスタンス化した際のインスタンスの初期値を固定させたい場合などに final 修飾子を付けます。


◆インスタンス変数の final 修飾子例

【final なインスタンス変数を持つクラス】

public class FinalTest {

	public final int number = 10; // final なインスタンス変数
	public int num = 5; // 通常のインスタンス変数
}

【インスタンス生成するクラス】

public class Test {

	public static void main(String[] args) {

		FinalTest test = new FinalTest();
		test.num = 10; // 通常の変数のため再代入可能
		test.number = 5; // final なため再代入不可
	}
}


グローバル変数の final 修飾子

広範囲で定数を使いたい場合、グローバル変数に final 修飾子を付けます。


◆グローバル変数の final 修飾子例

public class FinalTest {

	public static final int NUMBER = 100;
}



メソッドの final 修飾子

メソッドに final 修飾子を付けるとオーバーライドを制御することができます。

 ※メソッドの「オーバーロード」は制御対象にないため、許可されます。


◆メソッドの final 修飾子例

【親クラス】

public class FinalTest {

	public final void number(){
		System.out.println("オーバーライド不可");
	}
}

【子クラス】 親クラスの final 修飾子付きメソッドはオーバーライドできない❌

public class FinalTest2 extends FinalTest{

	// オーバーライド:エラーとなる
	public void number() {
	}
}


final 修飾子の付いたメソッドがオーバ―ロードできることも確認しておきましょう。


◆オーバーロードの例

public class FinalTest {

	public final void number(){
		System.out.println("オーバーライド不可");
	}
	
	public void number(int num) {
		System.out.println("オーバーロード可");		
	}
}

 ※もちろんオーバーロードしたメソッドに final 修飾子を付けることも可能です。



クラスの final 修飾子

クラスに final 修飾子を付けると、継承が不可となります。


◆クラスの final 修飾子例

【クラス①】

public final class FinalTest {
}

【継承しようとしたクラス②】 クラス①に final 修飾子が付いているため継承できない❌

public class FinalTest2 extends FinalTest{
}


余談

抽象クラスやインターフェースは、クラスへの継承や実装を目的にしています。

final 修飾子とは真逆の機能を持ち合わせているため、

抽象クラスやインターフェース自身には final 修飾子を付けられません。

ただし、抽象クラスが final 修飾子付きのインスタンス変数や具象メソッドを持つ事はできますし、

インターフェースが final 修飾子の付く定数を持つ事もできます。



配列の final 修飾子

配列に final 修飾子を付けると、インスタンスの参照先の変更ができなくなります。


◆配列の final 修飾子例

public class FinalTest {

	public static void main(String[] args) {

		final int[] array = new int[]{1, 2, 3};
		array = new int[] {4, 5, 6}; // final が付いているため新たなインスタンスを参照先にすることができない
	}
}


array に final が付いているため新たな参照先への変更ができません。

ちなみに配列の final 修飾子は配列が持つ値の変更ができてしまいます。

public class FinalTest {
	public static void main(String[] args) {

		final int[] array = new int[]{1, 2, 3};
		array[0] = 4;
		array[1] = 5;
		array[2] = 6;
	}
}


配列の値の変更を不可にしたい場合は、コレクションを使いましょう。

コレクションで配列が持つ値の変更を不可にすることができます。



コレクションの final 修飾子

配列の final 修飾子と同じく参照先の変更を不可にします。

これは例えば List インターフェースに属する他クラスへの変更も含みます。

サンプルコードでは ArrayList から LinkedList へ参照先変更を試みる例を書きます。

 ※コレクションがわからない方はコレクション紹介記事をご一読ください。


◆コレクションの final 修飾子例

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class FinalTest {
	public static void main(String[] args) {

		final List<String> array = new ArrayList<String>();
		array = new LinkedList<String>(); // array に final が付いているため参照先の変更不可
	}
}


上記の他、もちろん ArrayList から新たな ArrayList への参照先変更もできません。


コレクションの値を変更不可にする方法

コレクションの final 修飾子は配列と同じく、コレクションが保持する値の変更は制御しません。

コレクションの保持する値を変更不可にする場合は、

java.util.Collections が持つメソッド unmocifiable を使うことで読み取り専用に変更することができます。


 unmodifiable は List に使う場合は「unmocifiableList」、 Map で使う場合は「unmocifiableMap」、

 Set に使う場合は「unmocifiableSet」といったように unmocifiable の後に続くものが変わります。

 今回のサンプルコードでは unmocifiableList を使用します。



◆コレクションを読み取り専用にする例

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class FinalTest {
	public static void main(String[] args) {

		List<String> array = Collections.unmodifiableList(new ArrayList<String>());
		array.add("a");
	}
}


上記例では unmodifiableList の array に対して "a" を追加しようとしています。

コンパイル段階でエラーは出ませんが、実行時に UnsupportedOperationException の例外がスローされます。

これでコレクションが保持する値の変更を不可にしました。

配列の値を変更不可にしたい場合はコレクションの unmodifableList などを使うようにしましょう。



フィールドの final 修飾子(応用)

final 修飾子を使うとインスタンス生成以降、変更不可なフィールドの初期化も可能になります。


◆ final フィールドとコンストラクタの組み合わせ

public class ImmutableSample {

        private final int value;
        
        //コンストラクタで初期値を渡す(これ以降フィールドの値の変更不可)
        public ImmutableSample(int value) {
                this.value = value;
        }
        
        public int getValue() {
                return value;
        }
}


フィールドは private final なため、クラス外からのアクセスができず更に1度保持したデータは変更不可です。

コンストラクタからアクセスがあるため、

インスタンス生成時にフィールドはデータを保持して、

それ以降データの変更も外部からのアクセスもできないフィールドとなります。

(getter のように、クラス内メソッドからデータの参照は可能です)


保守性の高いクラスを作成できると実用的なプログラミング方法の幅が広がるため、

final 修飾子を有効活用しましょう。



まとめ

final 修飾子はクラスやメソッド、変数、配列などの変更を不可にできます。

変更不可にできる内容はそれぞれで異なるため、しっかりと覚えて活用しましょう。


関連記事リンク

インターフェースの紹介 / 継承とオーバーライドの紹介 / 変数の紹介 / メソッドの紹介 / コレクションの紹介 / クラスの紹介 / 配列の紹介 /  インスタンスの紹介 / 抽象クラスの紹介


【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様