2012/03/09

String.valueOfとLong.toString、どっちがいいのか考えてみた。

先日、String.valueOf(long l)とLong.toString(long l)はどっちを使うか?というツイートを読んで、なんとなく気になったので、久しぶりにJDKのソースをダウンロードして覗いてみた。

まず、String#valueOf(long l)
APIの 説明文には、「Long#toString(long l)と同じ※1」って書いてあるようにみえるけど、その下にあるソースコードは、実際には Long#toString(long i, int radix) を呼び出していた。
で、その中身をみてみる。



結局その先でLong#toString(long l)を呼び出していたので、※1の説明文は間違っていないことがわかった。

ということで、「プリミティブなlongの文字列表現を得る際に、StringおよびLongクラスのどちらのStaticメソッドを使うか?」は、結果的にどっちでも同じ。という結論。

ま、ここまでは、わざわざソースを確認しなくても、Java APIを読めばわかるし、冒頭のツイートも、そんなことを問題にしているわけでは無い。

で、Javaの設計思想的なことを考えてみた。
まず、Long。Longの存在意義は、プリミティブlongのお世話をするってのもあると思う。(←個人的主観です)
そうすると、LongにStaticメソッドとしてtoString(long l)を実装したのは理解できる。

そして、String。元来、Stringは文字列をイミュータブルに持つオブジェクトの役割を与えられていると思う。(←個人的主観です)一方で、便利に使えるように、オブジェクトではなく、クラスのStaticメソッドとしていろんなvalueOfメソッドが実装されている。

そうすると、以下のような書き方が出来てしまうことになる。

System.out.println("あ".valueOf(100l));
注:(”インスタンスがあるのにStatic呼び出しは推奨されない”って警告が出るから気付くことはできるけど、実行は出来てしまうので、新人プログラマなどが開発メンバーにいると、紛れ込むかもしれない。)


ただし、いくら便利とはいえ、String#valueOf(someType)なオーバーロードはちょっと自重したほうがいいんじゃないかな?というのが私の意見。

なぜか?

以下のコーディングがあります。文法的には問題ありません。

String a = String.valueOf(hogelong);
System.out.println(a);
String b = Long.toString(hogelong);
System.out.println(b);

でも、hogelongの宣言がものすごく遠くにあって、しかもこんな宣言だとしたら・・・どうなるでしょう。

char[] hogelong = null;

まず、String#valueOfを使った場合・・・
long型のようにみえたhogelongは実は、char型だったけど、オーバーロードの弊害で、コンパイルは通ってしまいます。そうすると実行するまでエラーに気付くことができません。

次に、Long#toStringを使った場合・・・
今度は、コンパイルの段階でエラーになってくれました。

どうやら安全性の観点では、Long#toStringに軍配があがりそうです。

以上








0 件のコメント: