プロが教えるわが家の防犯対策術!

下のようなコードを書いて、たとえば
java PossibleCompilerMalfunction Hello
のように実行すると、
Hello
と表示されることを期待していたのですが、
null
と表示されてしまいます。
(JDK1.5を使っています)

final String t = args[0];
の部分を
final String t = "Hello";
のように書き換えると、
Hello
と表示されます。

つまり、コンパイル時に「t」の値が決まっていなければ
nullになってしまうようです。

これってコンパイラのバグでしょうか。
あるいは私の考えに間違いがあるのでしたら、
指摘していただけるとありがたいです。


public class PossibleCompilerMalfunction {

public static void main(String[] args) {
final String t = args[0];
MyClass mc = new MyClass() {
void foo() {
System.out.println(t);
}
};
}
static abstract class MyClass {
MyClass() {
foo();
}
abstract void foo();
}
}

A 回答 (6件)

私の環境 (java/javac 1.5.0_06) で試したら


> java PossibleCompilerMalfunction Hello
に対してちゃんと
Hello
と表示されましたよ。

質問者さんのコンパイラは最新のものですか? もし本当に「null」と表示されたのなら確かにバグだと思います。

この回答への補足

ちょっと補足です。

>javacに常に「-target 1.1」というオプションをつける設定にしていたのを忘れてました。
このことを思い出したのは、
UKYさんの「コンパイラは最新のものですか? 」
という回答がきっかけだったことを書き加えておきます。

補足日時:2006/02/19 02:48
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

私の使ってるコンパイラは最新版です。
しかし、ひとつ謝らなくてはいけないことがあります。

古いJVMとの互換性を持たせるため、
(IEで動くアプレットを作ったりしているので)
javacに常に「-target 1.1」というオプションをつける設定にしていたのを忘れてました。
つまり私の環境では、
javac SomeClass.java
とタイプすると、下のように実行されるのです。
javac -source 1.2 -target 1.1 SomeClass.java

オプションをつけないでコンパイルしたら、
(すなわち「-target 1.5」でコンパイルしたら)
ちゃんと「Hello」と表示されました。
お騒がせしてすいません。

しかし、「-target 1.1」だと「null」になるのは
やはりコンパイラのバグだと考えてよさそうでしょうか。

お礼日時:2006/02/19 02:43

こんばんは。

回答というより補足情報です。

まず、メソッド変数にfinalを付けた場合は「一度代入された値または参照を変更できない」というもので、使用方法は問題ないと思います。

私の環境でも試してみましたが、nullと表示されました。
javac -J-version = 1.4.2_08
java -version = 1.5.0_06

mainメソッド内にMyClassをすべて定義する場合はHelloが出力されます。
また、mainメソッドの最後で、mc.foo();とするとHelloが出力されます。
問題はMyClassのコンストラクタがfoo()メソッドを呼んでいる箇所のようです。

やはり、コンパイラのバグでしょうか?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

koki_mさんのコンパイラは、バージョン「1.4.2_08」のようですね。
最新のコンパイラに代えたら、うまく行くかもしれません。
UKYさんの回答に対する「お礼」を参照してください。

お礼日時:2006/02/19 02:58

ANO4のtachiwaです。

文頭に”コンパイルエラー”と書きましたが、”コンパイラのハグ”と訂正してください。
    • good
    • 0

コンパイルエラーと断定は出来ませんが、UKYさんの主張が正しいと思います。

次のように t="World"; を追加するとコンパイルエラーが出力されます。
public class PossibleCompilerMalfunction {
public static void main(String[] args) {
final String t = args[0];
t="World"; //追記
MyClass mc = new MyClass() {
void foo() {
System.out.println(t);
}
};
}
static abstract class MyClass {
MyClass() {
foo();
}
abstract void foo();
}
}

javacの結果
PossibleCompilerMalfunction.java:9: final 変数 t に値を代入することはできません

t="World";
^
エラー 1 個
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
UKYさんの回答に対するコメントに詳細を書きました。

お礼日時:2006/02/19 02:46

finalとはまさに


「コンパイル時に値が決まっていなければならないもの」
です。
arg[0]はコンパイル時にはnullなので、コンパイラは間違っていません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

しかし、final変数は、コンパイル時に値が決まっていなければならないとは限らないのでは?
「ブランクfinal変数」というのもありますし、
たとえば下のようなコードは、コンパイル時には値が決まっていません。
final String userName = System.getProperty("user.name");

また、配列argsの大きさは
実行時のコマンドライン引数によって決まるので、
args[0]はコンパイル時には決まっていないのではないでしょうか。

お礼日時:2006/02/19 01:33

java の 変数の final 指定は定数ですから、


そうなりますね。

arg[0]は可変なのですから、final 指定しなければ、
OKでしょう。

参考URL:http://ux01.so-net.ne.jp/~komori/doc/java/final. …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

finalを指定しないローカル変数は
匿名クラス(あるいは無名クラス)からアクセスできないので
やむをえずfinalを付けました。

お礼日時:2006/02/19 01:26

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!