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というキーワードが存在しますが、存在するだけであって意味はありません。
よって、使用することはありません。