2011-04-15 9 views
12

私は、文字列の日付と時刻を解析するためのいくつかのメソッドを含むライブラリを作成しています。私は、文字列引数が解析できないときにそれらのメソッドがスローするべき例外を決定するのが難しいです。 - 無効な文字列は明らかに不正な引数ですが、私には、IllegalArgumentExceptionは通常、プログラミングエラーを意味し、それがいずれかの明示的なtry catchをやりたいことはまれだJava APIの設計:半数値文字列を解析するメソッドのNumberFormatException?

1. java.lang.IllegalArgumentException:私はいくつかのオプションを検討しています。私は、文字列の解析はしばしば外部入力用であり、特別な扱いを受ける特別なケースであると考えています。たとえば、ユーザー入力を解析して何か他のことをした大きなコードブロックがあった場合、try catchブロックにそのコードをラップして、無効な文字列を含むユーザー入力の大文字小文字を処理することができます。しかし、IllegalArgumentExceptionをキャッチすることは、無効なユーザー入力を正確に特定するためにはあまり役に立ちません。なぜなら、ユーザー入力パースだけでなく、スローされる可能性のあるコード内に複数の場所がある可能性が高いからです。

2. java.lang.NumberFormatException - それはjava.langInteger.parseInt(String)および他の同様の解析メソッドによってスローされます。だから、ほとんどのJava開発者は、有効であるかもしれない文字列(例えば、ユーザ入力)を解析しようとしているときに例外をキャッチすることに慣れている。しかし、それはその名前に「数字」を持っているので、ある意味では数値であるが、概念的には私の心の中では異なる日付や時刻には本当に合っているのか分からない。 "FormatException"とだけ呼ばれた場合...

3. java.text.ParseException - チェックされているため、実際にはオプションではありません。私はこれをチェックしないことを望む。

4.カスタム例外 - これはIllegalArgumentExceptionNumberFormatExceptionの欠点を回避して、それがあまりにもIllegalArgumentExceptionを拡張することができます。しかし、本当に必要な場合を除いて、ライブラリに例外を追加することは良い考えではないと思います。ジョシュ・ブロッホを引用して、"If in doubt, leave it out"。 (また、私の場合、日付と時刻を解析するパッケージでは、「DateFormatException」、「TimeFormatException」、「CalendricalFormatException」(JSR 310など)日付、時間などを解析します。そして、解析できない文字列を特定するために使用されているのであれば、複数の例外を1つのパッケージに作成するのはばかげているでしょう)

センス?

NB java.util.DateまたはJoda Time、つまりJSR 310を使用したくないという理由があります。そのため、それらを提案する必要はありません。さらに、この質問がかなり一般的に行われていれば、APIを設計している他の人たちが苦労している問題であるため、これが良いと思います。日時には、IPアドレスやURL、または解析が必要な文字列形式の情報の他の種類の情報もあります。その他のライブラリで設定し

先例は

ほんの一例は、私が見つかりました:

java.sql.Timestamp.valueOf(String) throws IllegalArgumentException

java.util.Date.parse(String) throws IllegalArgumentException(非推奨メソッド、および例外が宣言されていませんが、あなたがそれを見ることができますソース)

java.util.UUID.fromString(String) throws IllegalArgumentException

org.apache.axis.types.Time(String) throws NumberFormatExceptionは(Apache Axisの中にも、デイクラス)

org.apache.tools.ant.util.DeweyDecimal(String) throws NumberFormatException

com.google.gdata.data.DateTime.parseDateTime(String) throws NumberFormatException

java.lang.Package.isCompatibleWith(String versionString) throws NumberFormatException(Javaの7で、これはドットで文字列のバージョン番号がとる - の種類の中に日付や時刻のような感覚)

カスタム例外を使用するパッケージがたくさんあると思いますので、それらの例を挙げることに多くの点があるのでしょうか。

答えて

0

この質問については、味の問題です。私の意見では、私は例外をスローしませんが、その代償として扱います。その理由は、入力が間違っていると、ユーザーが例外ハンドラで何もできないためです。したがって、これらのタイプのエラーは、リターンコードをチェックすることで簡単に処理できます。例外は重く、余分な価値をもたらすものではありません。

+2

:)にそれがキャッチ望んで、私よ

...それ定義によって物事のJavaの道なり戻り値にエラーを含めることに強く反対します。これには、膨大なレスポンスオブジェクトまたは返されるObjectが必要です。両方とも、単純なAPIを使用できなくする可能性があります。 –

+0

+1 @ sean-patrick-floyd:nullが返される可能性があります。その場合、bloatはコード内にあり、再び使用できなくなります。 – subsub

+0

それは確かに味の問題です。私はparseOrNull(String)のようなメソッドを使用することを検討しましたが、コアJDKライブラリによって設定されたようなJavaのやり方に実際には合っていないと思います。加えて、100%が有効であると予想される文字列を解析している場合には、NullPointerExceptionを無駄にしたり、役に立たないNullPointerExceptionを取得したりすることになります。 –

3

私はIllegalArgumentExceptionから継承され(基本クラスとしてIllegalFormatExceptionを示唆しているだろうが、残念ながら唯一のコンストラクタをパッケージで保護されているので、私はおそらくいくつかのメソッド( 小さなAPIのため

  • IllegalArgumentExceptionを使用したいですそうでない場合はIllegalArgumentExceptionから継承)
  • 独自のクラス階層。

いずれにせよ、私はベースとしてIllegalArgumentException使用しますクラス。これは公式の教義ではありませんが

は、私の以前のプロジェクトの一つでは、ガイドラインは唯一

  • IllegalStateException
  • IllegalArgumentException
  • UnsupportedOperationException

から継承RuntimeExceptionsをスローするようにしました私はそれを良い練習と呼んでいます。これらの3つはすべてシンプルで自己説明的です。

+0

私はIllegalFormatExceptionを直接使用することを検討しましたが、Java 1.5+にのみ存在し、このライブラリは1.4互換です。 IllegalArgumentExceptionで始めることはうまくいくかもしれません。その後、ライブラリが成長するにつれ、互換性を損なうことなくサブクラスを作成して使用することができます。 –

+0

@MBと書いた通り:IllegalFormatExceptionは使用できません。アクセシブルなコンストラクタはありません –

+0

ああ、申し訳ありません。何らかの理由で私が最初にあなたのコメントを読んだとき、私はそのビットを、IllegalFormatExceptionを拡張できないと言っていると解釈しました。もちろん、パッケージプライベートコンストラクタだけでも、私はそれを現実的に使うことができませんでした。私は木の木を見るのに失敗していた! –

1

これは、DateFormat.parseがスローするため、ParseExceptionを選択します。したがって、2で言及する利点があります。プログラマーはそれに精通しています。しかし、チェックしたくないので、これはオプションではないと思います。チェックされていないことを余儀なくされると、私は4を選択します。

+0

おなじみはdefinitely goodです。しかし、私はチェック例外は、その種の解析メソッドのためにかなり扱いにくいと思う。整数を解析する場合と同様に、無効な可能性のあるユーザー入力を解析したい場合があります(例外を明示的にキャッチして処理したい場合があります)が、有効と思われるものを解析してからチェックされた例外は痛みになります。 –

+0

@MB:真。あなたができることの1つは、最初のケースの 'parse'や後者の' parseOrNull'や 'uncheckedParse'のように、これら2つのケースで異なる機能を提供することです。残念ながら(私は以下のparseOrNullのコメントを参照しています)、今はコアJava APIがこれを行う良い例は考えられません...また、KISSやInDoubtLeaveItOutの原則にも必ずしも従っていません。 – subsub

+0

内部使用のみの場合は、おそらくそれを実行します。 'parseOrNull'と' parseOrThrow'(解析に失敗した場合は未チェックの例外を投げます)は、実際に私が頻繁に使う規則です。しかし、あなたが言及した理由のために、それが公開APIにとって非常に良いとは思わない。私は人々を混乱させてしまうだろうと思っています。これまでに見たような大会ではないでしょうし、本当に自分の用語を理解するのではなく、できるだけ早く仕事をしたいと思うからです。 –

0

私は現在、NumberFormatExceptionを使用することに賛成しています。私はIllegalArgumentException昔ながらの考えていたが、それはそれは私のような少しのコードを書いたとき、理想的ではなかったことを私に明らかになった:

有効な Dayを解析すると仮定すると、
try { 
    final Day day = Day.fromString(userInputString); 
    someMethodThatCouldAlsoThrowIllegalArgumentException(day); 
} catch (IllegalArgumentException e) { 
    ui.showWarningMessage("Invalid date: " + userInputString); 
} 

を、あなたはそれで何かをしたいと思います。また、無効なパラメータ(ユーザーエラーではなくプログラミングエラー)を受け取った場合、渡すメソッドはIllegalArgumentExceptionになります。上の例のようなコードでは、無効なユーザー入力に対してプログラミングエラーを混同しないように注意したいと思うので、安全な側にするためにtry/catchブロックの前に定義されたnull変数のようなものが必要ですそれに続くnullのチェックを行います。

スワップIllegalArgumentExceptionNumberFormatExceptionまたはカスタム例外と問題がなくなります。

JDK 1.7の java.lang.Package.isCompatibleWith(String versionNo)は、バージョン番号( "1.6.1.32"のような半数値文字列)を解析する方法のため NumberFormatExceptionを使用して、私はこれはまた、のようなものを解析する方法のための賢明な選択であるかもしれないと考えていることを見た

日時。

NumberFormatExceptionは、半数値のみの文字列を解析するのには理想的ではありませんが、実際には必要ないカスタム例外を使用してAPIを混乱させたくない場合には最適なオプションです。彼らはjava.langでそれをやっている場合は、おそらくそれは私が、私は例外が重いことについて同意