Javaの正規表現の扱いはC#よりイイ!

以前「C#の正規表現の扱いはJavaよりイイ!」というエントリを書きましたが、訂正Javaの方がやっぱ良かったです。自分が知らなかっただけでした。すんません。

前回の例はエスケープ記号がつきすぎてしまうので、前回よりもう少し簡単な例として、以下のような文字列から年月日に関する数字情報を抜き出したい場合を考えます。

私は2009年3月24日に28歳になります。

期待値は

2009
3
24

です。
「28」を表示してはいけないということと「2009年」や「3月」ではなく「2009」や「3」を表示するってところに注意して欲しい。28がOKなら単に「パターンとして数字があれば」とすればいい。一方28を除くとなると単に数字ではなく「数字と年」といったパターンにしないといけませんが、求めているものは単位(っていうのかな?)を除いた数字のみ。つまり「パターン = 表示結果」ではないということがポイントです。
C#だと以下のようになる。targetという文字列型変数に上記文字列が入っているとして読んでね。

MatchCollection matches = new Regex("(?<1>[0-9]{1,4})[年|月|日]").Matches(target);
foreach (Match match in matches)
{
   Console.WriteLine(match.Groups[1].Value);
}

(?<1>・・・)を使うことで、パターンからさらに抽出したい部分が指定できる。
C#のこれに該当するものがJavaでは分からなかったんです。きっと同様にJavaオリジナルな書き方があるんだろうと思いこんでしまっていた。これがそもそもの誤り。javascriptrubyだとカッコで囲むだけで実現できるというのにC#がこうだったからJavaも特殊なんだろうと思いこんでしまっていた。
しかしやっとJavaでもこれと同等の書き方がやっと分かった。Javajavascriptrubyと同じやったんです。以下そのプログラム。

Matcher matcher = Pattern.compile("([0-9]{1,2})[年|月|日]").matcher(target);
while(matcher.find()) {
    System.out.println(matcher.group(1));
}

カッコで囲んだところがgroupメソッドの引数と対応しています。カッコが複数あれば1,2...と増えていきます。嗚呼分かってしまえばなんと単純な・・・。