• ベストアンサー

try~catchの使用方法

プログラミング超初心者です。 現在、C++やjavaの勉強をしているのですが、 ・try~catchとはなんぞや ・どんな処理をするときにtry~catchをつけなければいけないのか がよくわかっていないので、教えていただけないでしょうか? また、そういったことが載っているサイトも併せて教えていただければうれしいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

これは、「例外処理」のためのものです。 動きとしては、 try { ... } の中で発生した「例外」に対する処理を、 catch { ... } の中に記述しますということになります。 これは、例外(おおざっぱに言えば、内部的なエラー)の「発見」と「発生」と、「リカバリ」に関わる分離の思想から考えられたものです。 例外処理がない場合、エラーの処理は、 ・エラーが発生してないかどうか確認する ・エラーが発生していたら、その場で処理する ということになります。 この方法には、問題がああって、本来の処理とエラー処理が混在して処理の見通しが悪くなるということになります。 例えば、以前の(失敗したら NULL を返す仕様の new 演算子の場合) classA a = new classA(1, 0); if (a == 0) goto エラー処理; classA b = new classA(1, 1); if (b == 0) goto エラー処理; など。 これに対して、最近の(失敗したら、bad_alloc 例外をスルーする ) new だと、 try { classA a = new classA(1, 0); classA b = new classA(1, 1); } catch(bad_alloc) // これは、new で失敗した時に投げられる例外 { エラー処理 } となります。 こうすれば、if (a == 0) が本来の処理ではなく、エラーチェックだったのがわかります。 また、往々にして、エラーの検出箇所(それがエラーだったとわかる場所)と、エラーの発生場所(エラーを発生させてしまった場所)は違うものです。 例えば、平方根を算出する関数はマイナスの引数を受け付けません。このため、普通は関数の中で引数がマイナスでないかどうかチェックをします。 おかしな引数を渡していれば、関数の中で引数がおかしいかどうかわかります。 しかし、この間数の中では、なぜ引数がおかしいのかはわかりません。 入力ミスなのか、計算ミスなのか。 一方で、引数がおかしくなった原因は、この間数を呼び出す箇所(の近く)にあることが多いわけです。 ですから、おかしな引数のリカバリは、こちら(発生場所)で行う方が妥当です。 もちろん、関数を呼び出す前にあらかじめ引数の妥当性をチェックするというのも正しい考え方です。 ただ、場合によっては、通常処理の流れでプログラムを作り、その処理の中で(この部分を try で囲む)エラーが検出された箇所(実際には、例外処理がスルーされる場所)の情報をもとに、エラーのリカバリ(ここが、catch セクション)を行うという形にするとすっきりする場合があります。

その他の回答 (3)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

Javaはまだましですが、C++の場合、ありとあらゆる箇所で例外が送出される可能性があります。特にテンプレートを使った場合は、普通に演算子を使っただけでも例外に配慮する必要があります。 では、try~catch(正確には「監視ブロック(try-block)」といいます)は具体的にどんなところで使うかですが、送出された例外を処理することができる箇所、または他の例外に置換すべき場所で使用します。 送出された例外を処理することができない箇所に監視ブロックを入れてみても、どうすることもできずに、(臭いものに蓋をするように)単に例外を捨ててみたり、abort等で異常終了させるしかなくなります。例外が発生したときに、リソースの解放や状態の巻き戻しを行うためだけであれば、監視ブロックではなくデストラクタを使うべきです(Javaなら仕方ないでしょうが)。 別の例外に置換すべき場合というのは、モジュールの内部で発生した例外を外部に通知する場合に、実装の詳細に依存した例外から外部とのインタフェース用の例外に治してあげる必要がある場合などです。 例外処理というと、単に監視ブロックの使い方だけだと誤解されがちですが、実際には監視ブロックを使わない箇所での例外の扱いの方がずっと難しかったりします。「例外安全」または「exception safe」というキーワードで検索すれば、ある程度情報が得られるかと思います。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.2

同じく初心者ですが、おおまかに「予測不可能なエラー」対応に try/catch を使用します。 例えば、ファイルが存在しないとか、ユーザーが許容範囲を越える文字列を入力したとかは「予測可能」なので通常の if/else で対応して、 例えば、データベースとの接続が途中で切断されるなどは「予測不可能」なので try でつかまえて catch 節の中で対応する。その箇所で対応不能なら再度例外を throw する。 人によっては、ファイルの存在を確認せずにオープンしてみて、「ファイルが存在しない例外」を catch するようなコーディングをするかも知れませんが、私は好きでない。

Jet_Black
質問者

お礼

回答ありがとうございます。 「予測可能」 =if/else 「予測不可能」=try/catch ということですが、いかんせん初心者なもんで「予測可能」と「予測不可能」の違いがいまいちわかっていません。 データベースとの接続が途中で切断されるのは「予測不可能」となっていますが、それは、いつそんな事態が発生するかなんて「予測不可能」である、という意味でしょうか? せっかく教えていただいたのに何だかすいません。 勉強あるのみですかね・・・。

回答No.1

例外エラーが発生する可能性がある場合に利用します。 基本的に、tryで正常処理を行い、catchで例外エラーをキャッチしてエラー処理を行います。 Javaだと、仮にこんなプログラム public class test { public static void main(String[] args) { try { String[] hoge = new String[] {"abc", "def", "ghi"}; for(int i = 0; i <= hoge.length; i++) { System.out.println(hoge[i]); } } catch(ArrayIndexOutOfBoundsException e) { System.out.println("例外エラーが発生した場合に処理する"); System.out.println("配列要素の不足"); e.printStackTrace(); } finally { System.out.println("正常終了、例外エラー、どちらの場合でも必ず最後に処理する"); System.out.println("処理の終了"); } } }

Jet_Black
質問者

お礼

回答ありがとうございました。 サンプルコードまで載せていただいて、参考になりました。

関連するQ&A

  • “try/catch”と“if/else”

    プログラミング超初心者です。 以前、この掲示板でtry/catchとはどんなもので、どういう処理のときに使うものなのかという質問をさせていただいたのですが、そのときに ・if/elseは、ファイルが存在しないとか、ユーザーが許容範囲を越える文字列を入力したなどの『予測可能』な場合に使う ・try/catchは、データベースとの接続が途中で切断されるなどの『予測不可能』な場合に使う ということを教えていただいたのですが、『予測可能』と『予測不可能』の境目がわかっていません。 そこで ・具体的に、この処理のときは普通はtry/catchを使う というような処理を教えていただけないでしょうか? また、そのようなことが記載されているサイトなんかも教えていただければうれしいです。 私が周囲の人から聞いたのは、「COM、またはRPCなどの通信系の処理にはtry/catchを使う」らしいのですが、根拠がいまいちよくわかっていません。 Googleなどで調べてみてもそれらしい答えがないもので・・・。 よろしくお願いいたします。

  • try~catch

    php初心者です try~catchをわかりやすく教えてください throw new Exceptionが出現したら、catchまでの処理をしないでとばすとゆうことですか? try~catchを抜けたら、他の処理は普通に実行されるのでしょうか? try~catchのカッコ{で囲む範囲は大きくしたほうがいいでしょうか?(大きく囲むと処理スピードおそくなりますか?) try { throw new Exception('エラーが発生しました');  print "hoge"; } catch (Exception $e) {  echo '例外発生', $e->getMessage(), "\n"; }  print "foo"; よろしくお願いします

    • ベストアンサー
    • PHP
  • try~catchについて

    プログラム初心者です 繰り返し処理の中でtry~catchにスローしてもいいでしょうか?(正常にfor文は終了しますか?) try { for($a = 0; $a < 5; $a++) { if($a==3){ throw new Exception('3'); } } catch (Exception $e) { $msg = $e->getMessage(); } よろしくお願いします

    • ベストアンサー
    • PHP
  • 【C#/Java?】try-catchでcatchせずにfinallyは一般的?

    普段はJavaを使っているのですが、故あってC#のソースを簡易レビューすることになりました。 C#を始めてそれほど間もない人間の書いたソースなのですが、以下のようなソースをたびたびみかけます。 try {   // 処理 } finally {   // finally処理 } C#の場合、Javaとは異なり全ての例外はJavaで言うところの非チェック例外であると認識しています。(ただし、Javaの非チェック例外と同じ扱いをしていいとは思っていませんが……) 呼び出し元に起きうる全ての例外処理を任せるがfinally処理をしたいならば、このような書き方をするのが一般的なのでしょうか。 Javaの場合でもこのような書き方ができることは確認しましたが、Javaの場合は非チェック例外が起きる=バグであることがほとんどなので、このような書き方をする場面はあまりないように思います。 (もちろんチェック例外もthrowsを書けば同じように書くこともできるとは思いますが、自分ならやらないですし、そのようなソースを見たこともないです) ですので、単に自分がJavaを普段使っているからcatchがないことに違和感を感じるだけなのであれば、この問題はスルーしたいと思います。 C#経験者が周りにいない状況ですので、皆様のお知恵をおかりしたいと思います。よろしくお願いします。

  • 2つの“try ~ catch”

    こんにちは。 Javaの簡単なネットゲームのサンプルで勉強しています。 ゲームに使う変数[プレイヤー名、プレイヤー座標X,Y プレイヤー残体力]は、プレイヤーごとにハッシュテーブルに格納されることがわかりました。 JavaのハッシュテーブルのデータをJSObjectを使ってJavaScriptに渡したいのですが、ハッシュテーブルも、 JSObjectも try~catch を使っています。 ハッシュテーブルのtry~catch内でなければゲームに使う変数は取得できないと思うのですが、try~catch にJSObjectのtry~catchを入れ子にするようなプログラムの組み方がわかりません。 このような場合どのように組むのでしょうか? ご教授ください。

  • PDO で try~catch 構文を使う場所は?

    PHP5のPDOはtry~catch構文に対応しているのですが、どのように使えばいいのでしょうか? SQLを発行する度に、もしくはSQLを発行するメソッドの度に、try~catchしなければいけないのでしょうか?とても面倒です。 現時点では、例外が発生した時にする処理といえば、 trigger_error($e->getMessage(), E_USER_ERROR); みたいに、trigger_error するだけです。 であれば、そもそもcatchせずに、uncaught のまま勝手にエラったままに放っておいても問題ないのでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • try catch 文について

    jcpadでプログラムを組んでいます。  コンパイル実行すると 「例外 java.io.IOException は報告されません。スローするにはキャッチまたは、スロー宣言をしなければなりません。」 というエラーがでるのですが、BufferedReaderやDataInputStreamでは 例外処理(try~catch)は必ず書かないといけないんですか?

    • ベストアンサー
    • Java
  • try catchについて

    try catchの動きで質問があります。 以下が簡略化したソースです。 -------ここから--------------------- ストリーム1; ストリーム2; try{ try{ //ストリーム1を使った処理 }catch(IOException e){ throw e; }finally{ //ストリーム1のクローズ } try{ //ストリーム2を使った処理 }finally{ //ストリーム2のクローズ } } catch(IOException e){ throw new hogeException(); } ------ここまで-------------------------- 内側でスローされた例外は、外側でcatchされるのですか? また、内側でcatchをしなかった場合、外側でcatchされるのですか? この2点を教えていただきたいです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • PowerShell try~catchについて

    現在、Powershellでスクリプトを作成中ですが、動作がうまくいかず困っております。 スクリプトには以下のコードを記述しています。 簡単に書くと、対象のディレクトリにある作成から90日を超えたアイテムを削除、削除できたら"成功"、削除できなかったら"失敗"と表示します。 $log_dir #削除するファイルが入っているディレクトリ $message1 = "削除完了" $message2 = "削除失敗" try { #作成から90日経過したファイルを削除  Get-Childitem $log_dir | Where-Object [$_.LastWriteTime -lt (Get-Date).AddDays(-90)} | Remove-Item #削除完了メッセージ表示  Write-Host $message1 } catch { #削除失敗メッセージ表示 Write-Host $message2 } 現時点で$log_dirに90日を超えてないファイルがあったとします。 その際は削除されないのですが、上記のコードのままだと$message1が表示されてしまい、catchにいきません。 どう修正すれば、catchに行くでしょうか? Powershell初心者のため、申し訳ございませんが、ご教示をお願いいたします。

  • Try-catch文(FileInputStream)

    下記コードでエラーが出現して困っています。 fis.close();の部分でコンパイルエラー( 変数 fis は初期化されていない可能性があります。)の結果が返ってきます。 必ず通過するfinallyブロックにclose()処理を記述して、この処理もエラーが発生する可能性があるので、try-catchする必要があると教師が言っていました。 エラーが出現する原因はなぜでしょうか? 回答のほどよろしくお願い致します。 FileInputStream fis; try{ fis = new FileInputStream(fi.getAbsolutePath()); while( (b[i++] = fis.read()) != -1); }catch(FileNotFoundException e){ } catch(IOException e){ }finally{ try{ fis.close(); ←コンパイルエラー( 変数 fis は初期化されていない可能性があります。) }catch(IOException e){ } }

    • ベストアンサー
    • Java

専門家に質問してみよう