Apache commonsが便利な件(commons-lang編)

http://d.hatena.ne.jp/daisuke-m/20080702/1214982943

やー、前書いたエントリいつだったかな、と思って見たら7月ですよ。コツコツ書いていきますね。まず初回はcommons-lang。

commons-lang は、java.langパケにあるような基本的なクラスを追加で提供している感じです。また、既存の基本クラス(String,Object,配列等)のメソッドに対してnullチェックを搭載したものが多く提供されています。null対策を内部で行っているので、ぬるぽを恐れる必要があまりありません。こういうのを使いこなせると便利ですね。

StringUtils

これはよく使いますかね。もしかしたらcommonsで一番知名度の高いクラスかもしれない。しかしその中でマイナーかもしれないのはまず定数系。下記の例では、後者の方が記述量は多くなりますが、「コードで語れ」てます。

if(x.equals("")) { ... }
if(x.equals(StringUtils.EMPTY)) { ... }

if(y.indexOf(z) == -1)  { ... }
if(y.indexOf(z) == StringUtils.INDEX_NOT_FOUND)  { ... }

その他、メソッドはStringのメソッドに対してnull対策を施したものが多数。前者はfooがnullだった時はぬるぽが飛びますが、後者はnullが入ります。

String foo = ...;
String bar = foo.trim();
String baz = StringUtils.trim(foo);

そんなnull対策でよくやるのが、こんなコード。

if("hoge".equals(x)) { ... }

しかし、どうも美しくない。これはこう書くと美しいかも。

if(StringUtils.equals(x, "hoge")) { ... }

ObjectUtils

上記StringUtilsによるnullチェックと同様、Objectに対するnull対策済みメソッドを提供。例えば x.equals(y) は、xのnullチェックが要るケースが多いが、ObjectUtils.equals(x, y) でいい。

identityToString

hashCodeやtoStringをオーバーライドしてしまったクラスで、ObjectオリジナルのtoStringの結果を使いたい場合。

defaultIfNull
Object x;
if(y == null) {
  x = z;
} else {
  x = y;
}

じゃなくて、こう書ける。

Object x = ObjectUtils.defaultIfNull(y, z);

Object x = y == null ? z : y; とも等価だけど、ObjectUtils使った方が分かりやすい。。

ClassUtils

Classオブジェクト用ユーティリティ。

クラス表現文字列(com.example.Foo$Bar 等)の構成要素が定数として定義されている。下記1行目よりも、2行目の方がやりたいことが明確。コードで語る。

String[] x = y.getClass().getName().split(".");
String[] x = y.getClass().getName().split(ClassUtils.PACKAGE_SEPARATOR_CHAR);
getShortClassName, getPackageName

com.example.Foo という文字列が欲しければ、x.getClass().getName()
でいいのだが、Fooだけが欲しい時、ありますよね。FQCNじゃ、なげーよ、というとき。

ClassUtils.getShortClassName(x) でどうぞ。逆にパケ名だけ欲しいときは getPackageName で。

SystemUtils

システムプロパティが定数化している。

String x = System.getSystemProperty("file.separator");
String x = SystemUtils.FILE_SEPARATOR;

その他、JavaバージョンやOSなどの判定メソッドなど。user.homeをFileオブジェクトとして取得するメソッド等も便利(getUserHome())。

ArrayUtils

まず、各種基本オブジェクトの空配列が定数として定義されている。以下の2文は同義です。

return new String[0];
return ArrayUtils.EMPTY_STRING_ARRAY;
toString

ListオブジェクトをSystem.out.printlnする*1と、"[A, B, C]" のように要素が並んで表示されるが、配列を表示しようとすると "[Ljava.lang.String;@107077e" こんなあまり嬉しくない文字列になる。その辺の解決。"{a,b,c}" という感じ。

コレクションのように配列を扱うメソッド群

ArrayUtils.isEmpty(array) など、配列をあたかもコレクションのように操作するユーティリティがいっぱいあります。reverse, indexOf, lastIndexOf, contains, add, addAll, remove, removeAllなどなど。

その他
  • 配列のequals比較
  • clone
  • subarray(substringみたいに一部切り出し)
  • 素数の取得と比較(null対策済み)

Validate

メソッドの事前条件など、値検証用のユーティリティ。

Validate.notNull(argument);
Validate.notEmpty(array);
// 等...

CharRange, CharSet

あんまり使うこともないかもしれないけど、「文字の範囲」をあらわすクラス。

CharRange cr = new CharRange('c', 'e');
assert cr.contains('d') == true;
assert cr.contains('x') == false;
cr = new CharRange('c', 'e', true); // 反転
assert cr.contains('x') == true;
assert cr.contains('d') == false;

よく使うものは定数としてCharSetクラスに定義されている。

CharSet.ASCII_ALPHA = new CharSet("a-zA-Z");
CharSet.ASCII_ALPHA_LOWER = new CharSet("a-z");
CharSet.ASCII_ALPHA_UPPER = new CharSet("A-Z");
CharSet.ASCII_NUMERIC = new CharSet("0-9");

例外

例外も定義されています。黙って使用例を見ると分かります。

public void foo(Object obj) {
 if (obj instanceof String == false) {
   throw new IllegalClassException(String.class, obj);
 }
 // do something with the string
}

public void foo(PersonSearcher search) {
 if (search.getSurname() == null ||
     search.getForename() == null ||
     search.getSex() == null) {
   throw new IncompleteArgumentException("search");
 }
 // do something with the searcher
}

public void foo(String str) {
 if (str == null) {
   throw new NullArgumentException("str");
 }
 // do something with the string
}

public void foo() {
 try {
   // do something that throws an Exception
 } catch (Exception ex) {
   // don't know what to do here yet
   throw new NotImplementedException("TODO", ex);
 }
}

継承関係はこんな感じ。

  • IllegalArgumentException
    • IllegalClassException
    • IncompleteArgumentException
    • NullArgumentException
  • UnsupportedOperationException
    • NotImplementedException

ToStringBuilder

toStringを作るのって、結構大変。それをサポートしてくれるのがこのクラス。

public class Person {
  String name;
  int age;
  boolean smoker;

 // ...

  public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }
}

toString結果は "Person@7f54[name=Stephen,age=29,smoker=false]" など。
フィールド数が多くて1行表示だと見づらい場合は、第二引数にフォーマットが指定できる。

どう使うかは貴方次第、Mutableシリーズ

primitiveラッパーオブジェクト(Integer,Boolean等)はimmutableであることで有名です。足したり引いたり、とにかく値が変わるとインスタンス自体が置き換わるクラスです。

じゃあ、Mutableなラッパーがあってもいいじゃないか、というシリーズ。

StrBuilder

StringBuilderの強力版。appendlnメソッドが便利。最後に改行をつけてくれるんですね。その他色々な便利メソッドが追加されています。

しかし、StringBuilderはfinalクラスなのでextendsできません。力技で作っているクラスです。

その他、見てみると面白いかもしれないクラス

  • LocaleUtils
  • WordUtils
  • StringEscapeUtils
  • RandomStringUtils
  • DateUtils
  • DateFormatUtils
  • StopWatch (ちょっとしたパフォーマンス測定に使える)


以上、すべてではありませんが、個人的に気に入っているクラスを中心に紹介しました。これでcommons-langに興味を持った方は、他のクラスも覗いて見るといいと思います。ちなみに commons-lang (v2.4) は約80クラスしかなく、ほとんどのクラスが独立している(依存していない)ので、非常に読みやすいライブラリだと思います。

*1:toStringする