Javaで文字列をfinal修飾子でクラスの中に定義した際の動きでハマったことがあったので記録します。
発生した事象は以下の通り。
[事象]
クラスAでfinalで定義した文字列をクラスBを呼び出していた。
このクラスAの中の文字列を変更し、クラスAをクラスファイルを再作成する。
クラスBは再度作成はセずそのまま使用する。
クラスBは実行すると、クラスAの以前の値が使用される。
[原因]
final定義した文字列は、クラスファイル作成時に呼び出し元のクラスに直接値が埋め込まれる。
[テスト]
以下の2つのクラスを用意する。
値を設定したクラス
public class values {
public String value1=”value1″;
public static String value2=”value2″;
public static final String value3=”value3″;
public static String getValue4(){
return “value4″;
}
private static String value5=”value5″;
public static String getValue5(){
return value5;
}
private static final String value6=”value6”;
public static String getValue6(){
return value6;
}
}
呼び出し元クラス
public static void main(String[] args) {
String value2=values.value2;
String value3=values.value3;
String value4=values.getValue4();
String value5=values.getValue5();
String value6=values.getValue6();
}
クラスファイルを作成し、jadでデコンパイルする。
デコンパイルの方法はこちらのページからご確認ください。
呼び出し元クラスをデコンパイルすると以下のようになる。
public static void main(String args[])
{
String value2 = values.value2;
String value3 = “value3”;←ここが変数から書き換わっている
String value4 = values.getValue4();
String value5 = values.getValue5();
String value6 = values.getValue6();
}
値を設定したクラスを変えてもfinal で定義されたvalue3だけが値が変わらないことがわかります。
値を設定しているクラスをデコンパイルしてみても同様の記述になっております。
public class values
{
public values()
{
value1 = “value1”;
}
public static String getValue4()
{
return “value4”;
}
public static String getValue5()
{
return value5;
}
public static String getValue6()
{
return “value6”;←ここが変数から書き換わっている
}
public String value1;
public static String value2 = “value2”;
public static final String value3 = “value3”;
private static String value5 = “value5”;
private static final String value6 = “value6”;
}
本来であれば変数として定義されていたvalue6が値に直接入れられていることがわかります。
finalをつけるだけで変化するが、あまり認識されていない動きだと思いますのでご参考になればと思います。