Javaでは、メソッドからイテレータを返す必要があります。私のデータは、通常はイテレータを提供できる別のオブジェクトから取得されているため、それを返すことができますが、状況によっては、基になるデータがnullになります。一貫性を保つために、その場合は「空の」イテレータを返したいので、呼び出し元はnullをテストする必要がありません。
私は次のようなものを書きたかった:
public Iterator<Foo> iterator() {
if (underlyingData != null) {
return underlyingData.iterator(); // works
} else {
return Collections.emptyList().iterator(); // compiler error
}
}
しかし、JavaコンパイラはIterator<Object>
ではなくIterator<Foo>
を返すことについて文句を言います。(Iterator<Foo>)
へのキャストも機能しません。
次の構文を使用して、Foo型の空のリストを取得できます。
return Collections.<Foo>emptyList().iterator();
Java7は長い間リリースされています。以前のJavaバージョン用に開発しているのでない限り、次のような空のイテレータを返します。
return Collections.emptyIterator();
私はもっと行きます
public Iterator<Foo> iterator() {
if (underlyingData == null)
return Collections.<Foo> emptyList().iterator();
return underlyingData.iterator();
}
ただ、特別な場合を処理して戻り、次に通常の場合を処理します。しかし、私の主なポイントは、あなたが割り当てを回避できるということです
Collections.<Foo> emptyList().iterator();
google-collections でCollections.<Foo>emptyList().iterator()
を提供する主な理由はIterators.emptyIterator()
の煩わしさです。あなたのような場合、型パラメータは必要ありません。
これは、Java型推論がすべての場合に機能するとは限らず、三項演算子が明らかに同等のif-else構文と常に同等であるとは限らないことを示していると思います。
また、次のように述べたいと思いますnull
は避けてください。また、Iterator
sは奇妙なステートフル動作をするため、渡さないでください(Iterable
を推奨)。ただし、これを行う正当な、時期尚早ではない理由があると仮定すると、私の好ましい書き方は次のようになります。
public Iterator<Foo> iterator() {
return getUnderlyingData().iterator();
}
private List<Foo> getUnderlyingData() {
if (underlyingData == null) {
return Collections.emptyList();
} else {
return underlyingData;
}
}
IMO、推測できる場合は(コードが長くなっても)推測可能な型情報を挿入しないことをお勧めします。
ほぼ確実に複数回実行するので、ローカル変数を宣言するだけでなく、getUnderlyingData
メソッドを挿入します。
両方の結果でiterator
を呼び出しているので、繰り返さないでください。
すみません、わかりました。コンパイラがパラメータ化された型を理解できるように、割り当てを使用する必要があります。
public Iterator<Foo> iterator() {
if (underlyingData != null) {
return underlyingData.iterator();
} else {
List<Foo> empty = Collections.emptyList(); // param type inference
return empty.iterator();
}
}
public final class EmptyIterator{
public static Iterator iterator(){
return new Empty();
}
private static class Empty implements Iterator {
public boolean hasNext(){
return false;
}
public Object next(){
throw new NoSuchElementException();
}
public void remove(){
}
}
}