初期化
経験則として、変数を宣言するときに変数を初期化してみてください。
変数の値が変更されないように意図されている場合は、final
キーワードを使用して明示的にします。これは、コードの正確性を判断するのに役立ちます。キーワードを認識するコンパイラーまたは JVM の最適化については知りませんがfinal
、それらは確かに可能です。
もちろん、この規則には例外があります。たとえば、変数は if–else またはスイッチで割り当てることができます。そのような場合は、ダミー値が読み込まれる前に上書きされることが保証されている初期化よりも、「空白」宣言 (初期化のないもの) を使用することをお勧めします。
/* DON'T DO THIS! */
Color color = null;
switch(colorCode) {
case RED: color = new Color("crimson"); break;
case GREEN: color = new Color("lime"); break;
case BLUE: color = new Color("azure"); break;
}
color.fill(widget);
これでNullPointerException
、認識できないカラー コードが表示された場合に表示されます。無意味な を割り当てない方がよいでしょうnull
。コンパイラは、color.fill()
初期化されていない可能性があることを検出するため、呼び出し時にエラーを生成しますcolor
。
この場合、あなたの質問に答えるには、問題のコードを確認する必要があります。ソリューションがrun()
メソッド内で初期化した場合は、一時ストレージとして、またはタスクの結果を「返す」方法として使用されている必要があります。
コレクションが一時ストレージとして使用され、メソッドの外部からアクセスできない場合は、インスタンス変数ではなくローカル変数として宣言する必要があり、ほとんどの場合、メソッドで宣言されている場所で初期化する必要があります。
同時実行の問題
初心者向けのプログラミング コースの場合、講師はおそらく並列プログラミングの複雑さに直面しようとはしていませんでしたThread
。しかし、現在の CPU 設計の傾向により、プログラミングを学んでいる人は誰でも並行性をしっかりと把握する必要があります。ここはもう少し掘り下げてみます。
スレッドのrun
メソッドから結果を返すのは少しトリッキーです。このメソッドはRunnableインターフェースであり、複数のスレッドがrun
単一インスタンスのメソッドを実行するのを止めるものは何もありません。結果として生じる並行性の問題は、Java 5 で導入されたCallableインターフェースの背後にある動機の一部です。これは によく似Runnable
ていますが、スレッドセーフな方法で結果を返すことができException
、タスクを実行できない場合は をスローできます。
少し余談ですが、興味のある方は次の例を考えてみてください。
class Oops extends Thread { /* Note that thread implements "Runnable" */
private int counter = 0;
private Collection<Integer> state = ...;
public void run() {
state.add(counter);
counter++;
}
public static void main(String... argv) throws Exception {
Oops oops = new Oops();
oops.start();
Thread t2 = new Thread(oops); /* Now pass the same Runnable to a new Thread. */
t2.start(); /* Execute the "run" method of the same instance again. */
...
}
}
メソッドの終わりまでに、main
メソッドの「状態」が何であるかはほとんどわかりませんCollection
。2 つのスレッドが同時に処理を行っていますが、コレクションを同時に使用しても安全かどうかは指定していません。スレッド内で初期化すると、少なくとも最終的にstate
は 1 つの要素が含まれると言えますが、それが 0 か 1 かはわかりません。