2012-03-23 20 views
1

私はJavaにとって非常に新しいです。私は、ファイルを読み込み、そのSHA1チェックサムを計算し、その結果を別のファイルに書き込むプログラムを書いています。エラーが発生した場合は、stderrにメッセージを出力し、指定された終了ステータスのSystem.exit()を呼び出して実行を終了する関数err_exit()を呼び出しています。これは私のmain()関数がどのように見えるか、およそ次のとおりです。Java:例外と '初期化されていない可能性があります'

public static void main(String[] args) { 
    String in_fname = "C:/tmp/test.txt"; // not reading args yet 
    String out_fname = "C:/tmp/test.sign"; 
    byte[] file_data; 
    String hexdigest; 

    try { 
     file_data = readFileAsByteArray(in_fname); 
    } 
    catch (java.io.IOException ex) { 
     file_data = new byte[] {0}; // note this line well, please 
     err_exit(2, "error opening input file '" + in_fname + "'"); 
    } 

    try { 
     hexdigest = hexdigestSha1(file_data); 
    } 
    catch (NoSuchAlgorithmException ex) { 
     hexdigest = ""; // note this line well, please 
     err_exit(3, "could not compute SHA1 message digest!"); 
    } 

    try { 
     writeFileFromString(out_fname, hexdigest); 
    } 
    catch (java.io.IOException ex) { 
     err_exit(2, "error writing output file '" + out_fname + "'"); 
    } 

    System.exit(0); // success 
} 

私はよく注意することは、あなたを尋ねた2行があります。これらの行は、変数が初期化されていない可能性があるとコンパイラーが不平を言わないようにするためだけに存在します。

コンパイラが知る限り、catchブロックは続行される可能性があります。実際にerr_exit()は返されないので、無効な値が渡されることはありません。

私の質問:この種のことを処理するための通常のJavaイディオムは何ですか? try/catchブロックの行は醜いものです。さまざまな機能をerr_exit()と呼び、このようなコードを明示的に使用しないことをお勧めしますか?私は明示的なチェックを好むと思うし、main()機能がチェックを行うのに適切な場所ですが、私はフィードバックに興味があります。

try/catchブロックを使用する予定がある場合、これはコンパイラの警告を消すのに適した方法ですか?

私がこれをPythonでやっていたのであれば、例外をキャッチせずにスタックトレースでプログラムを停止させることができます。エラーのスタックトレースは、そのユーザーが私であるので、このプログラムのユーザーに衝撃を与えません。 main()という関数をthrows Exceptionとして宣言すれば、例外をキャッチできず、Pythonのような振る舞いをすることができます。それは正しい考え方のJavaの人々を私に惑わせる恐ろしい考えですか?

P.S.あなたが好きな本/ Webページ/私が読むべきJavaのイディオムがあれば、それに言及してください。

EDIT:変数名にアンダースコアを付けてお詫び申し上げます。私はすでに自分の実際のプログラムでそれらの名前を変更しましたが、ここでそのまま残します。実際には、私はPythonとCでプログラミングに多くの時間を費やしてきたからです。私はPythonの「PEP 8」スタイルまたは一般的なCスタイルのいずれかを使用していました。

+0

これらの2つの変数を宣言する行を投稿します。 –

+0

不足しているものを追加して完全な機能にしました。 StackOverflowが構文カラーリングをやっているので、もっと良く見えます。 – steveha

答えて

2

強いCの背景があるようです。私は、コンパイラがfile_dataのような変数について不平を言うと仮定します。単にtry-catchブロックの上にfile_data = nullを追加してください。

上記のいくつかの点:

  1. 私は一つのブロック内のすべての文を結合しても安全だと思います。例外がスローされると、プログラムはすぐに正しい例外ブロックに分岐します。それはまた、はるかに少なく醜い見えます。
  2. 通常、他のメソッドはキャッチブロック内で呼び出されません。タスクは(通常は可能な限り)短く、ポイントにする必要があるからです。エラーを処理し、続行または終了します(おそらく例外を再スローします)。
  3. System.exit()は悪です。システムを終了させたい場合は、ラップされたRuntimeExceptionをスローします(つまり、回復不可能なエラー状態)。 System.exit()はクリーンではないことがあります。代わりにを使用して新しいRuntimeException(e)をスローします。
  4. 最後に、私が鈍いかもしれない場合、Javaのコンベンションでは、メソッド/変数名をerr_exitではなくerrExitとして記述します。私はなどreadFileAsByteArray、呼び出しの結果に行為する試みで、失敗したアクセスの直後に出たことだろうと陽性であった場合
+0

Hmmm。私が質問を投稿する前に、私はいつもStackOverflowを検索して答えがあるかどうかを調べます。 "この変数は初期化されていないかもしれない"というエラーについては数多くの議論があり、そのうちのいくつかは "必要になるまで変数を初期化しないでください;コンパイラに助けを与えたいと思っています。コンパイラがあなたを助けることができない変数を初期化してください。あなたは一般的にそのアドバイスに同意しないのですか? – steveha

+0

あなたの質問を編集しました:-)警告の観点から、byte [] file_data = null;を試してください。 RuntimeExceptionはあなたのためのスタックトレースを表示します...私はあなたが望むものだと思うので。 –

+0

コンパイラの不満を避けるために初期化しても問題ないと思います。通常、怠惰な初期化は完全な意味を持ちますが、実際の値(つまりnull以外)が分かっている場合のみです。私は "変数= nullを使用しています;"年齢のローカル変数のために...私は誰かがそれが悪いスタイルであると私に言うなら、私は最も驚くでしょう(そして、私は間違いなく代替をしたい)。 –

0

、私はおそらく宣言でnull値を代入したいですサイト。このようなもの...

byte[] file_data = new byte[] {0}; 

...残りのコードは、キャッチブロックの「偽の」割り当てなしで続きます。

2

コンパイラは、スローが返されないことを理解していますが、err_exit()は返されないことを理解していません。あなたが無視している例外を使って書き直すなら、あなたのコードはより洗練され、コンパイラがより幸せになれます。 Java命名規則の使用を検討することもできます。

public static void main(String[] args) { 
    String inFname = "C:/tmp/test.txt"; // not reading args yet 
    String outFname = "C:/tmp/test.sign"; 
    try { 
    processFile(inFname, outFname); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    throw e; // rethrow and let main() die 
    } 
}   

public static void processFile(String inFname, String outFname) 
    throws IOException, NoSuchAlgorithmException { 
    Byte[] fileData = readFileAsByteArray(inFname); 
    String hexDigest = hexdigestSha1(fileData); 
    writeFileFromString(outFname, hexDigest); 
} 

エラーをキャッチすることができます。 IOExceptionが発生する可能性のある別の場所を区別する必要がある場合は、ルーチンをキャッチして記述的なエラーをスローすることができます。

あなたのコードに対する最小限の修正は、変数を設定するtry catchブロックの外でnullに初期化することです。コンパイラはうれしいでしょう。

+0

覚えておいてください。あなたの答えをJaco Van Niekerkの答えと合わせると、「new_timeout(mesg)」に渡すことで、「some_file_nameファイルを読み込めません」というようなメッセージを指定すると思います。 – steveha

+0

私は2つの答えを受け入れることができれば、私もこれを受け入れるだろう。私はそれをupvoteでした。ありがとう。 – steveha

2

個人的には、私は「nullを投げる」のが好きです。単純に返すことのできないメソッドを呼び出した後。

関連する問題