ITエンジニア日記 ~NO SKILL, NO LIFE~

学んだ技術や、気になることをアウトプットしていきます。プログラミング, インフラ, etc...

Javaのfinal修飾子 と C++のconst修飾子

変数の値を書き換えられたくないとき、Javaだとfinal修飾子を、C++C言語だとconst修飾子を変数に付けて定数として宣言します。

両方とも変数への値の再代入を禁止するための修飾子ですが、Java の final と C++ の const では少し働きが異なります。

今回は、final と const の違いを説明します。

[目次]

1. C++ の const修飾子

C++の const は冒頭で説明したように、変数への再代入を禁止するための修飾子です。

たとえば、constを付けたdouble型変数のpiに対して、値を再代入しようとするとコンパイルエラーになります。

const double pi = 3.14159;     // const変数宣言
pi = 10;     // コンパイルエラー

また、配列やクラスのような場合でも const は data1[] や data2 という変数に対して再代入禁止とするため、値の再代入はコンパイルエラーとなります。

const int data1[] = { 1, 2, 3, 4, 5 };     // 配列のconst変数
data1[1] = 10;     // コンパイルエラー

const std::vector<int> data2(5, 2);     // 要素数5、すべての値を2で初期化したvector配列
data2[0] = 10;     // コンパイルエラー

const std::vector<int> data3(10, 2);
data2[0] = data[3];     // コンパイルエラー

2. Java の final修飾子

Javaの final も、変数への再代入を禁止するための修飾子です。

基本型変数に final を付けた場合、C++の const と同様に変数に値を再代入しようとするとコンパイルエラーとなります。

final double pi = 3.14159;     // final変数宣言
pi = 10;     // コンパイルエラー

ところが、参照型変数の場合は少し異なります。 final修飾子が禁止するのは再代入であり、参照先のオブジェクトの変更ではないのです。

次のコードで、"data1[1] = 10;" は参照先のオブジェクトの変更にあたるため、コンパイルエラーにならず動作します。

しかし、"data1 = new int[10];"は新たなインスタンスを再代入することになるのでコンパイルエラーとなります。

final int[] data1 = new int[] { 1, 2, 3, 4, 5 };     // 配列のfinal変数
data1[1] = 10;     // 1. 参照先のオブジェクトの変更
                   // エラーにはならず、値の代入ができる

data1 = new int[10];     // 2. 再代入
                         // コンパイルエラー

Javaで変数の参照先のオブジェクトの内容の変更を禁止する仕組みは用意されてないと思うので、自分で実装する必要があります。

(もし、仕組みあったらすみません。)

3. まとめ

Javaの final修飾子とC++の const修飾子についてみてきました。

Javaでfinal修飾子を使うときは、変数の型が基本型参照型かで動きが変わるので注意しましょう。

豆知識

Javaにもconstというキーワードが存在しますが、存在するだけであって意味はありません。

よって、使用することはありません。

参考

  • 谷本心/阪本雄一郎/岡田拓也/秋葉誠/村田健一郎 「Java 本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで」 株式会社技術評論社