はじめに
ちょっと前になりますが、ADTが一部を除いてJava7に対応しましたね。
(try-with-resourcesはminSdkVersionの19のようですね。)
ADTプラグインの説明の22.6.0の説明
こちらのブログがとても分かりやすく書かれています。(切り身こわい)
さて、話は変わってGoogle製のJavaライブラリ、Guava。
Androidでも、Android以外でもJavaでの開発に使っている方も多いのではないでしょうか?
先日、Google+のGuava公式アカウントがGuava APIs obsoleted by JDK7というタイトルで投稿をしていました。
以下、Guava APIs obsoleted by JDK7より
While Guava doesn't require JDK7, there are a bunch of Guava APIs that have been obsoleted by JDK7. If you're using JDK7, you should prefer the built-in JDK7 APIs over the Guava APIs; at some point, we may remove these APIs from Guava. Here’s a list of obsoleted Guava APIs and their JDK replacements:
-instead of c.g.c.base.Charsets.UTF_8, prefer java.nio.charset.StandardCharsets.UTF_8 (same goes for the other constants in our Charsets class)
-instead of c.g.c.base.Objects.equal(), prefer java.util.Objects.equals()
-instead of c.g.c.base.Objects.hashCode(), prefer java.util.Objects.hash()
-instead of c.g.c.collect.Iterators.emptyIterator(), prefer java.util.Collections.emptyIterator()
-instead of c.g.c.primitives.Booleans.compare(), prefer java.lang.Boolean.compare() (same goes for the other compare() methods in our primitive wrapper classes)
-instead of the static factory methods for creating collections (e.g. Lists.newArrayList()), prefer the constructors with the diamond operator (e.g., new ArrayList<>())JDK8 obsoletes a ton of Guava APIs, so we’re hard at work figuring out what a JDK8-friendly version of Guava will look like!
なるほど。
よく使うものが並んでいますね。
こちらの投稿に関するコメントで大変勉強になるものがいくつかあったので、そこで言われていたことに、自分の考えを追加してまとめました。
Objects#equalとLists#newArrayListは、無くなっちゃ悲しいし、Guavaの方が便利ですね。
という話です。
GuavaのObjects#equalとJava7のObjects#equals
次のようなコードがあるとします、
String a = getString();
String b = getString();
if(a.equals(b)){
// 略
この場合getStringがnullを返し得るならば、aがnullの場合NullPointerExceptionになってしまうので、nullでないか事前のチェックが必要です。
このようにオブジェクトがnullの場合まで含めたequlasの比較はGuavaのObjects#equalメソッドが便利です。
次のコードはGuavaのObjects.equalの使用例です。
System.out.println(Objects.equal("hoge", "hoge")); // true
System.out.println(Objects.equal(null, "hoge")); // false
System.out.println(Objects.equal("hoge", null)); // false
System.out.println(Objects.equal(null, null)); // true
String a = getString();
String b = getString();
if(Objects.equal(a,b)){
// 略
// ただしaもbもnullな場合真なことに注意
このObjects.equalはObjectのメソッドは、equalsメソッドをオーバーライドする際にも大変役立ちます。
さて、Java7にはjava.lang.Objectsクラスにequalsというメソッドがあります。
Guavaのcom.google.common.base.Objectsのequalメソッド
Java7のjava.lang.Objectsクラスのequalsメソッド
どちらも二つのObject型の引数をとり、nullの対処も同じです。
非常に良く似ていますが、大きな違いがあります。GuavaはequalでJava7はequalsです。sの違いです。このsによって、あることがGuavaではできますが、Java7ではできません。
メソッドのstaticインポートです。
Javaのすべてのクラスの親クラスObjectクラス。このクラスはいくつかのメソッドを持っていますが、Object型一つを引数にとるequlsもその一つです。
そのため、Java7のequalsメソッドはstaticインポートが書けません。それに比べて、Guavaはstaticインポートが可能です。
import static com.google.common.base.Objects.equal;
//略
Hoge a = createHoge();
Hoge b = createHoge();
if(equal(a,b)) { // staticインポートしているので、equalだけの記述でOK
// anything TODO
}
Hoge a = createHoge();
Hoge b = createHoge();
if(Objects.equals(a,b)) { // 「if(equals(a, b))」はコンパイルエラー
// anything TODO
}
まぁ、正直次のやつにくらべたら無くなっても、いいかなという感じですが...
GuavaのLists#newArrayListとJava7で導入されたダイヤモンドオペレーター
Java7はダイヤモンドオペレーターにより次のように、型の記述がすこし簡略化できるようになりました。
List<String> list = new ArrayList<>();
実は、GuavaのLists#newArrayListも型推論をしてくれるので、インスタンス化の方の型の記述をしなくてもいいです。
List<String> list = Lists.newArrayList();
// 上記メソッドをstaticインポートすれば
// List<String> list = newArrayList();
// でいい。
これだけであればわざわざGuavaを導入しなくても、単純にダイヤモンドオペレーターを使えば良いとも思えるのですが、GuavaのLists#newArrayListには、次のように初期化できるオーバーロードが用意されています。
List<Strng> list = Lists.newArrayList("H", "e", "l", "l", "o");
// static importすれば、
// List<String> list = newArrayList("H", "e", "l", "l", "o");
このように簡潔に初期要素こみのListのインスタンスを作成できます。
ArrayListのコンストラクタには、このように簡潔にインスタンス化できるものは無いです。コンストラクタは、
- 引数なし
- int型 (初期容量指定)
- Collectionを実装した型 (初期要素指定)
の3個です。3個目のCollectionを実装した型を引数に取るものを使ったとしても、次のように書く必要があります。
List<String> list = new ArrayList<>(Arrays.asList("H","e","l","l","o"));
(ちなみにArrays.asListもListインターフェースを実装したインスタンスを作成しますが、addメソッドなどを呼び出すと、UnsupportedOperationExceptionを投げます。)
(参考:Java7のArrayListのAPIリファレンス)
ちなみにC#では次のように、Listを初期化できます。
var list = new List<string> {"H", "e", "l", "l", "o"};
Groovyもリストのインスタンス化は、次のような便利な記法が用意されています。
def list = ["H", "e", "l", "l", "o"]
Javaのリストの初期化は少々冗長です。ダイヤモンドオペレーターで少しは短くなりましたが、GuavaのLists#newArrayListを使うとさらに短くすることが可能ですね。
その他投稿にあったもの
c.g.c.base.Charsetsとjava.nio.charset.StandardCharsets
InputStreamReaderクラスなどの初期化に用いるCharset型の定数です。
new InputStreamReader(new FileInputStream(file),StandardCharsets.UTF_8)
// or
new InputStreamReader(new FileInputStream(file), Charsets.UTF_8)
参考:Where to get “UTF-8” string literal in Java?
参考:java.nio.charset.StandardCharsets
参考:com.google.common.base.Charsets
c.g.c.base.Objects.hashCode()とjava.util.Objects.hash()
どちらもhashCodeを作る便利メソッドで、内部的にArrays.hashCode(Object[])が呼ばれるようですね。
これはequalsと逆で、Guavaのメソッドの方がObjectのほうと同じメソッド名でjava.utils.Objectsの方が違うメソッド名ですね。そのため、java.utils.Objectsのhashメソッドの方はstaticインポート可能ですね。
参考:java.util.Objects#hash
参考:com.google.common.base.Objects#hashCode
c.g.c.collect.Iterators.emptyIterator()とjava.util.Collections.emptyIterator()
自作コレクションなどに使うのでしょうか?
ちなみに、java.util.Collections.emptyList()やjava.util.CollectionsCollections.emptyMap()もありました。どちらも、add・putしたら、UnsupportedOperationExceptionが発生しました。
参考:java.util.Collections#emptyIterator
参考:com.google.common.Iterators#emptyIterator
プリミティブ型のラッパークラスのcompareメソッド
Guavaはcom.google.common.primitivesという名前空間にBooleans、Ints、Doublesなど、プリミティブ型の便利クラスがあります。
com.google.common.primitives.Booleans.compareのドキュメントには、
Java7以降ならjava.lang.Boolean.compareを使おうとありました。
参考:com.google.common.primitives.Booleans#compare
参考:java.lang.Boolean#compare
Guavaについての分かりやいページ
- guava-libraries 公式
Qiita(@disc99 さん) Javaの便利ライブラリ Google Guava
eller's blog Guavaをざっくり紹介
プログラマ的京都生活 guava
しかじろうがなんか作るよ Google製Javaライブラリ Guavaを使ってみた。
まとめ
やっぱり、Guava便利ですね。
Java7で加わったメソッドも要チェックですね。