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

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

ただいまの
回答率

90.53%

  • Java

    15528questions

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

  • コーディング規約

    52questions

    コーディング規約とは、コードの書き方についての決め事のことです。 文法のことではなく、そのチームなどの中の約束事としてどのような書き方で行うかを定めるもの。 項目の例として、関数や変数の命名規則、コーディングのスタイル、括弧やインデントの書き方などが挙げられます。

例外を投げるだけの関数を作ってよいか。

解決済

回答 8

投稿

  • 評価
  • クリップ 2
  • VIEW 3,179

koikuti

score 21

前提・実現したいこと

javaの決まりというか、慣習というか分かりませんが、引数によって何らかの判定を行い、
判定にマッチした場合例外を投げるだけの関数を作ることはjavaのルールや慣習として許されているでしょうか。

関数の説明

  • 呼び出し元からチェック用の変数を引数として受け取る。
  • 特定の値であれば例外を投げる。
  • 上記の特定の値意外であれば、何もせず呼び出し元に処理が戻る。

該当のソースコード

例えばこんな感じ

private void errorCheck(String checkTarget){
    if(checkTarget.equals("hogehoge")){
        throw new SystemException("システムエラー");
    } else if(checkTarget.equals("fugafuga")){
        throw new BusinessException("業務エラー");
    }
}

試したこと

戻り値をvoidでなく、booleanとして例外とならなかった場合は常にtrueを返し、
呼び出し元では戻り値を受け取らず、処理を続行する。

private boolean errorCheck(String checkTarget){
    if(checkTarget.equals("hogehoge")){
        throw new SystemException("システムエラー");
    } else if(checkTarget.equals("fugafuga")){
        throw new BusinessException("業務エラー");
    }
    return true;
}

気になる部分

該当のソースコードについて

  • 呼び出し元から見ると、void型の関数を呼んだにもかかわらす処理が終わってしまう事がある。
  • 関数名がcheckとなっているが boolean の戻り値でない。
    試してみたことについて
  • 戻り値を boolean と言いつつ、true OR Exception を返すような作りになっている。(正確には例外は返していないが...)
  • 呼び出し元では、戻り値がある関数であるにも関わらず、その戻り値を受取る必要がない。(受け取らない。)

ご回答の程よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

+5

私の個人的な見解では、慣習的な Javaコードとは言えません。

なぜなら、『Effective Java 第2版』(丸善出版)が 第9章 項目57 で
「例外的状態にだけ例外を使用する」
べき、と主張しているからです。

同書は、Javaプログラマのバイブル的な書籍です。
(少なくとも、私はそう思っています(^^;)

ご提示のerrorCheckメソッドは、引数checkTargetが正当な値か否か、そしてどのように不正なのかをチェックするためのメソッドだと見受けます。
であれば、このメソッドに不正な値が渡されることは、「例外的状態」とは言えません。
(それをチェックするためのメソッドなのですから)

大替案として、以下のようにエラーコードを返却する、というのはいかがでしょうか?

private static final int VALID = 0;
private static final int SYSTEM_ERROR = 1;
private static final int BUSINESS_ERROR = 2;

private int errorCheck(String checkTarget){
    if(checkTarget.equals("hogehoge")){
        return SYSTEM_ERROR;
    } else if(checkTarget.equals("fugafuga")){
        return BUSINESS_ERROR;
    }
    return VALID;
}


これなら、例外を投げることなく、修正前のコードと同じ目的を果たすことができます。

ちなみに、なぜ「例外的状態にだけ例外を使用する」べきかは、上述の『Effective Java』を読んで確かめてみてください。
一応、私なりに要約すると、以下のようになります。

  • 可読性が悪い。
  • 例外に基づくイデオムは、標準のイデオムより遅いか、将来的に JVM のバージョンアップによって遅くなる可能性が高い。
  • try/catch句の使用を強制するため、別の場所で発生した例外を隠蔽してしまうかもしれない。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+3

本来はそのcheckTargetを返すメソッドこそが例外を出力すべきだとは思いますが、外部システムと連携している場合など、レスポンスの文字列を判断して処理する流れにせざるを得ない、そして、それを例外に変換し、throwする処理があっても私はよいと思います。checkというメソッド名が気になるなら、validate(検証)はいかがでしょうか。

もしくは、checkTargetを返すメソッドを持ったクラスを更にラップしてしまって、例外判定まで含めた上でcheckTargetの文字列を返すものを作ってみてはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

根本的にこういうメソッドが適当かはさておき、作るとしたら「返り値はvoid」で「throwsを書く」という形にすれば、インターフェースレベルで「何も返さないけど例外が飛ぶことがある」というのがはっきりしていいと思います(非検査例外もてthrowsに書けます)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

「もしエラーなら例外をスローする」ということをするためのメソッドなら、戻り値なしで例外をスローするだけというのは何ら問題ありません。エラーチェック用のメソッドを作ることはごく一般的に行われていますし、私もよくやります(Javaは使いませんがC++とかC#で)。
ただ、メソッド名はそれと判るような名前を付けた方が良いかもしれません。私ならthrowIfErrorとかthrowIfInvalidのような名前にします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

private void throwIfError(String checkTarget) throws SystemException, BusinessException{
    if(checkTarget.equals("hogehoge")){
        throw new SystemException("システムエラー");
    } else if(checkTarget.equals("fugafuga")){
        throw new BusinessException("業務エラー");
    }
}


と、しました。

説明不足だった部分があり申し訳ないのですが、外部システムとの連携などの関係で、
どうしても、Exceptionを発生させてエラーメッセージをやり取りする必要があり、
ちょっとおかしな場所(?)でExceptionを投げざるを得なくなり、気になった次第でした。

様々なご意見ありがとうございます。

ベストアンサーには、私の説明に漏れていた、外部システムとの連携等も考慮に入れてくださった、masaya_ohashiさんとさせていただきます。

その他のご意見も、ためになるご意見ばかりでした。
本当にありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ObjectsクラスのrequireNonNullメソッドのように、引数がnullでない時は引数そのものを返すようにすればいいのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

私ならやらない方法ですね。

以下、個人的な意見です。

例外は大域脱出の方法であり、問題がありこのメソッドはこれ以上の処理を進められませんという場合にのみ使うと決めているからです。

大域脱出をするかしないかは、呼び出し側のメソッドが決めるほうがメソッドの独立性が担保できる気がします。

また、チェック処理をまとめると、何がどうして問題になるかわからないので、問題になる処理の直前にチェックを入れる方法を好みます。また、少し複雑なチェックの場合は、個別にチェックメソッド(bool IsDuplicate(string id)など)を定義しておくと正常処理の邪魔になりずらいです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

Webアプリケーションの入力値検証(validation)では、許可できない入力値の場合に例外をスローする実装(ないしはフレームワーク)が多いようですね。

ただし例外ですので、呼び出し元ないしはこの例外を制御している箇所までに、取得しているリソースを開放できているかを気にしないといけません。
それでなければ、矢鱈滅多に例外をスローするのは少々乱暴にも見えます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Java

    15528questions

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

  • コーディング規約

    52questions

    コーディング規約とは、コードの書き方についての決め事のことです。 文法のことではなく、そのチームなどの中の約束事としてどのような書き方で行うかを定めるもの。 項目の例として、関数や変数の命名規則、コーディングのスタイル、括弧やインデントの書き方などが挙げられます。