web-dev-qa-db-ja.com

try / catchを使用した最終的な変数の割り当て

私はそれが良いプログラミング慣行であると信じているので、一度だけ書かれることを意図している場合、すべての(ローカルまたはインスタンス)変数をfinalにします。

ただし、変数の割り当てが例外をスローできる場合、その変数を最終的にすることはできません。

final int x;
try {
    x = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
    x = 42;  // Compiler error: The final local variable x may already have been assigned
}

一時変数に頼らずにこれを行う方法はありますか? (または、これは最終修飾子の正しい場所ではありませんか?)

62
dtech

これを行う1つの方法は、(非[final)一時変数を導入することですが、それはしたくないと言いました。

別の方法は、コードの両方のブランチを関数に移動することです:

final int x = getValue();

private int getValue() {
  try {
    return Integer.parseInt("someinput");
  }
  catch(NumberFormatException e) {
    return 42;
  }
}

これが実用的であるかどうかは、正確なユースケースに依存します。

全体として、xが適切にスコープされたローカル変数である限り、最も実用的な一般的なアプローチは、_final以外にすることです。

一方、xがメンバー変数である場合、私のアドバイスは初期化中に非finalテンポラリーを使用することです。

public class C {
  private final int x;
  public C() {
    int x_val;
    try {
      x_val = Integer.parseInt("someinput");
    }
    catch(NumberFormatException e) {
      x_val = 42;
    }
    this.x = x_val;
  }
}
57
NPE

いいえ、それは正しい場所ではありません。tryブロックとcatchブロックで1つ以上のステートメントを取得したと想像してください。最初のステートメントはx = 42です。 x = 30と言います。これでxを2回定義しました。

0
SomeJavaGuy