概要
Scala に Try という便利なものがあると知りました。Java で似たようなものができないかを試してみました。
scala.util.Try
例外が発生しうる処理をラップして Pattern match できる仕組みです。2.10.0 以降で使えるそうです。
Try
Try {
String.format("http://%s/robots.txt", new URL(urlStr).getHost)
} match {
case Success(url) => Some(url)
case _ => None
}
この例では new URL(urlStr) のところで不正なURL(例:プロトコルが違う)が渡されると MalformedURLException が発生します。例外が発生した場合は case _ に入って None が返されます。例外が発生しなかった場合は Success の case で処理されます。
Scala の Try を Java で実装してみようとする
Java のソースコード
例外が発生しうる処理を action で、例外発生時に実施する処理を onFail で、それぞれ渡すことができるようにしてあります。
Try.java
import java.util.concurrent.Callable;
public class Try {
private Runnable onFail;
private boolean suppressError;
public Try suppressError(final boolean suppressError) {
this.suppressError = suppressError;
return this;
}
public Try onFailure(final Runnable onFail) {
this.onFail = onFail != null ? onFail : () -> {};
return this;
}
public <T> T action(final Callable<T> action) {
try {
return action.call();
} catch(final Exception e) {
if (!suppressError) {
e.printStackTrace();
}
onFail.run();
}
return null;
}
}
使い方
client_side
public static void main(final String[] args) {
System.out.println(extractedHost("http://www.yahoo.co.jp/index.html"));// 成功
System.out.println(extractedHost("htto://www.yahoo.co.jp/index.html"));// 例外発生
}
private static String extractedHost(final String url) {
return new Try()
.onFailure(() -> System.out.println("fail"))
.action( () -> new URL(url).getHost());
}
やっていること
- Try オブジェクトを初期化
- onFailure で例外発生時に実施する処理("fail" と println する)を渡す
- action で試行する処理(String オブジェクト url を URL オブジェクトに変換して、host 部を抜き出す)を渡す
実行結果
実行結果
www.yahoo.co.jp
java.net.MalformedURLException: unknown protocol: htto
at java.net.URL.<init>(URL.java:600)
at java.net.URL.<init>(URL.java:490)
at java.net.URL.<init>(URL.java:439)
at jp.toastkid.libs.Try.lambda$2(Try.java:37)
at jp.toastkid.libs.Try.action(Try.java:18)
at jp.toastkid.libs.Try.extractedHost(Try.java:37)
at jp.toastkid.libs.Try.main(Try.java:30)
fail
null
感想
正直、あまり便利な感じがしませんでした……Optional と組み合わせて使わないと意味もなさそうな気がします。