質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

Q&A

解決済

8回答

22003閲覧

例外の存在理由がよくわからない

Anoaji

総合スコア49

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

11グッド

11クリップ

投稿2016/02/25 01:06

11

11

###例外について
プログラミングは例外処理がついてまわるものだと思いますが、コンパイルエラーになること以外で、なぜ例外をキャッチ・あるいは投げなければならないかが不明です。

###疑問点
下のソースコードはDB接続の際の、凡庸な例外コードです。疑問が4つあります。

①例外が起こると強制終了になるが、キャッチしても同じことでは
(エラー画面にならないことがメリット?)

②の箇所に書く正しい処理はこれで正しいか?(エラー原因を突き止めるだけでいいのか。だとしたら、エラー処理が強制な理由がしっくりきません)

③この箇所にたどりつくまでにconがnullになる時はどんな時か

④よく本でfinally文で例外をキャッチしてもやることないため処理は不要ですと書いてありますが、僕にとっては他のキャッチ箇所もログを出すだけであれば、ここもprintstacktrace();を書けばいいのにと思ってしまいます。

###ソースコード

//例外文のみ catch(SQLException e){ e.printstacktrace();・・・・・・② }finally{ if (con != null){ ・・・・③ try{ con.close(); }catch(SQLException e2){ //処理は不要・・・・・・④ } }
kutsulog, dsk, LLman, Manabu_K, Stephen_J, Bear.Antarctic, ai_2013_dev, Aeona, pinnkoro, ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答8

0

ベストアンサー

①例外が起こると強制終了になるが、キャッチしても同じことでは?

(エラー画面にならないことがメリット?)

複数スレッドで動いている場合などは影響が該当スレッドだけでおさまります

②の箇所に書く正しい処理はこれで正しいか?(エラー原因を突き止めるだけでいいのか。だとしたら、エラー処理が強制な理由がしっくりきません)

商用で使うプログラムなどでしたらエラー原因の解析は必須です
(原因のわからないエラーは恐怖でしかありません ロジックの誤りなのかデータの異常なのか)
あと、例外が発生した場合に後続処理をさせずにソフトランディングさせる意味でもcatchは必要です

③この箇所にたどりつくまでにconがnullになる時はどんな時か

処理本文が乗っていないので何とも言えません
conのNewに失敗したとかconをNewする前に例外が発生したとかでしょうか

④よく本でfinally文で例外をキャッチしてもやることないため処理は不要ですと書いてありますが、僕にとっては他のキャッチ箇所もログを出すだけであれば、ここもprintstacktrace();を書けばいいのにと思ってしまいます。

この例のように処理がcloseだけならば原因はもっと前にあるからとかではないでしょうか?
別に書いても問題はないと思います。

投稿2016/02/25 01:33

kutsulog

総合スコア985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/25 03:29 編集

つまり、 ①「プログラム全体を止めたくない場合は例外が必要」ってことですね! ② >原因のわからないエラーは恐怖でしかありません 確かにこれはその通りですね。エラー原因究明のためにキャッチは必要な気がしました。 >ソフトランディングさせる つまり、キャッチした場合に、その中で処理をがっつり書くんでしょうか?あまり見たことがありませんが、、 ③なるほどです!newが失敗の時もキャッチされ終了しますね! ④ >処理がcloseだけならば原因はもっと前にあるからとかではないでしょうか? あまりイメージがわきません。。closeの際に例外が起こったら原因はそこなのでは、、と思ってしまいます。
kutsulog

2016/02/25 04:18

2のソフトランディングさせるのは ・後続処理をさせないことで誤ったデータを登録しない ・データの一貫性を持たせるためDBのロールバックをさせる ・作業途中を示すために配置している空ファイル(またはディレクトリ)を削除する 等がよくある話です closeは基本解放処理がメインになることが多いです 解放でエラーが起こるのは大抵確保に失敗しているためです 確保でエラーメッセージを出しているので解放でエラー出す出さないは方針によると思います (開放する配列要素の数で判定に誤りがある場合もあるのでログを出させるのはありだと思います) あとcloseに失敗するとそれ以上終了のためにできる手段がないというのもありますね
Anoaji

2016/02/27 06:44

>データの一貫性を持たせるためDBのロールバックをさせる >確保でエラーメッセージを出しているので解放でエラー出す出さないは方針によると思います この辺が実体験もあり、相当イメージが湧きました。kutsulogさんのような詳しいエンジニアが近くにいたらどれだけ苦労しないか、、と思いました。 >あとcloseに失敗するとそれ以上終了のためにできる手段がないというのもありますね ちなみに「接続のクローズに失敗」した場合、**再度クローズさせる**ってことをすればいいのに、、と素人目で思ってしまいます。ただそれだとネストが永久に深くなってしまいそうですね。詳しくありがとうございます。
guest

0

Javaはキャッチを強制される「検査例外」があるので事情が違いますが、他の言語では例外を投げっぱなしにしても特に問題ありません。キャッチされない例外が起きれば、確実にそこで終了してくれます。もし何かしらの対策を行うのであれば、キャッチして続けることも可能です。

例外のないC言語では、返り値やグローバル変数で異常事態を通知していましたが、これらは呼び出す側で参照しなければただ無視されてしまいます。例外の場合は、「何もしなければエラーで落ちる」ということで、より安全になっています。

なお、4のように「例外をキャッチした上で無視する」ことも可能です。ふつうはよろしくない形ですが、ここの場合は「接続のクローズに失敗」したところで、「できることもなければ何かをする必要もない」ということで、ただ無視させています。

投稿2016/02/25 01:40

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/25 03:27 編集

>確実にそこで終了してくれます。もし何かしらの対策を行うのであれば、キャッチして続けることも可能です。 強制終了でも問題ないと思っていたので、例外の必要性が不明でしたが、後続処理が必要な時に、例外が必要なんですね。後続必要ないならログ確認のためって感じでしょうか。 ちなみに「接続のクローズに失敗」した場合、**再度クローズさせる**ってことをすればいいのに、、と素人目で思ってしまいます。
guest

0

コンパイルエラーと例外は発生するタイミングが異なるので比較にはならないです。
また、エラー処理をするか、例外で扱うかは宗教論争的な面もありますので、開発しているプロジェクトのルールに従えば良いと思いますが、想定される問題はエラーで、動作時に想定されない問題を例外で扱うと個人的には考えています。

基本的にAシステムとBシステムはどちらも強調して動作する、両方が動いていないことはないという前提のシステムにおいて、AシステムからBシステムが動いているかを毎回チェックして、Bシステムが動作していないので、動かしてくださいというメッセージを利用者に提示する必要はなく、運用者に迅速に伝えることの方が必要です。
そのような場合に例外を使うとかでしょうか。

また、開発時には例外画面を出して、スタックトレースを出した方が問題解決に直結するという意味ではおっしゃる通りと思いますが、本番の際に、問題が発生した場合にどこまで何をすべきかというのは、上に書いたようにプロジェクトの方針に依存するのではないかと思います。
最近はクラッシュレポートのためのライブラリもありますので、適宜利用すれば良いかと。

投稿2016/02/25 01:14

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/25 03:17

>AシステムからBシステムが動いているかを毎回チェックして、 >Bシステムが動作していないので、動かしてくださいという >メッセージを利用者に提示する必要はなく、運用者に迅速に >伝えることの方が必要です。 エラー処理にしない理由は非常に納得です。また、強制終了でない理由としては、例外書かないと、運用者に自動で伝わらないためタイムロスがもったいないってことでしょうか?
t_obara

2016/02/25 04:12

タイムロスが勿体無いか否かはそのシステムを利用したサービス価値により決まるものですが、例示したシステムにとってはそのようにすべきという意図です。
guest

0

(1) についてですが、

java

1// For文 2for (int i = 0; i < storeList.size(); i++) { 3 try { 4 // 一店舗ごとに処理します 5 } catch(Exception e) { 6 // もし仮にA店でコケても、続けてB店を処理したいのでcatchする 7 } 8}

みたいな使い方とかします。

あとは

「CSVファイルを読み込んでDBに取り込む。
処理後、CSVファイルは
成功した場合はokフォルダへ、失敗した場合はngフォルダへ移動する」

みたいな処理の場合、もしDB更新に失敗しても
そのあとの「ngフォルダへのファイル移動」処理を実行しないといけないので
そういう場合もキャッチしたりしますね。

投稿2016/02/25 02:09

sk_3122

総合スコア1126

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/25 02:57

確かに続けて処理を行ないたい場合は、例外キャッチしたほうがいいですね。勉強になります。
guest

0

例えばDBをあれこれするライブラリがあって、
DBへの接続に失敗した場合にどうするかは、
ライブラリ作成側が決めることではなく、
利用側が決めることです。

再接続したい場合もあるでしょう。
何が起こったかログ書いて後は異常終了でいい場合も有るでしょう。
何もしないでいいやと言う場合もあるでしょう。
とにかく、非常事態に何をするかは自由に決めたいわけです。

このように、何か異常があったとき、何をするかを利用側に決めさせる仕組みの一つが
よくある例外機構です。

投稿2016/02/25 10:08

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/26 13:17

なるほど。javaは検査例外に関しては強制だから、なぜ?と思ってしまいましたが、状況によって対応を変化できるための仕組みとして存在してると考えたほうがよさそうですね
guest

0

ここなどわかりやすく書かれています。参考になれば幸いです。

http://www.atmarkit.co.jp/ait/articles/1111/01/news131.html

投稿2016/02/25 09:11

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/27 06:33

わざわざリンク探していただいてありがとうございました。これまで見た中でもかなりわかりやすかったです。
guest

0

例外処理機構は、とても大事な問題を含んでいます。
回答になりませんが、参考になるページを幾つか紹介します。

...
プログラムの実行中に例外的な状況になってプログラムの実行順番を変えたい場合が在ります。
しかし、例外が起きる可能性のあるところに、いちいち条件分岐のプログラムを書くと、プログラムの流れがとても解りにくくなります。
めったに使われることの無い、プログラムの本流ではない処理が頻繁にプログラムの中に出てくると、本来の流れが把握できなくなるのです。
さらに、例外に対応するには関数呼び出しを遡って処理する必要が出てきたりしますから大変です。
C言語のプログラムであれば、例外が起きるところでは例外の有無をチェックして処理部へgoto文で跳ぶ形のプログラムを書くことになるでしょう。
しかしgotoでは自由度が在りすぎて例外処理のパターンが定まりません。
そこで、java言語やC++言語には例外処理の手順が構文として用意されています。
...

...
例外
近年では、エラーが発生した際は例外メカニズムで処理すべきという認識を大方の人が持っているようです。
少なくともエラーコードを返す方法が最適でないことについては誰も異論はないでしょう(私もありません)。
エラーコードを介した処理よりもっと豊かで、実用性と堅牢性を兼ね備えたものが必要ですよね。

例外の問題は、このメカニズムが実際はgoto文をベースにしたものだということです。
先ほど、goto文は害悪であると学んだばかりですよね。
...

...
我々は、処理構造を制御するためのtry-catch-finally形式の例外処理機構によって、コードが入り組んでしまうと考えています。
しかも、ファイルを開けないといった、ごく一般的なエラーをさも特別なエラーであるかのように扱わせる傾向があります。

Go言語では、異なるアプローチを取りました。

Go言語では戻り値として複数の値が返せるので、一般的なエラーハンドリングの場合、戻り値といっしょにエラー情報を返すことができます。
エラー型は標準化されており、Goの他の機能と相まってエラーハンドリングがすっきりしたものとなります。
これは、他の言語と大きく異なる点です。
...

投稿2016/03/01 13:12

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

.netでの話ですが、とある人はブレークポイントを設定する為だけにCatchを書いていました。当然Catchの中身はthrowのみ。開発中ならいざ知らずリリース版にまで残す処理じゃないよね・・・

投稿2016/03/04 05:15

Ryzna

総合スコア85

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問