在Java中,我需要从我的方法返回一个Iterator。我的数据来自另一个通常可以给我一个迭代器的对象,所以我可以返回它,但在某些情况下,底层数据为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>)
也不起作用。
答案 0 :(得分:58)
您可以通过以下语法获取Foo类型的空列表:
return Collections.<Foo>emptyList().iterator();
答案 1 :(得分:26)
Java 7已经出现了很长时间。除非您正在为以前的Java版本开发,否则您将返回一个如下所示的空迭代器:
return Collections.emptyIterator();
答案 2 :(得分:9)
我会更多地遵循
public Iterator<Foo> iterator() {
if (underlyingData == null)
return Collections.<Foo> emptyList().iterator();
return underlyingData.iterator();
}
只是,处理特殊情况并返回,然后处理正常情况。但我的主要观点是你可以用
来避免作业Collections.<Foo> emptyList().iterator();
答案 3 :(得分:4)
Collections.<Foo>emptyList().iterator()
的烦恼是我们在google-collections中提供Iterators.emptyIterator()
的主要原因。在像你这样的情况下,不需要类型参数。
答案 4 :(得分:2)
我想这表明Java类型推断在每种情况下都不起作用,并且三元运算符并不总是等同于明显等效的if-else结构。
我还想说明避免null
。还要避免传递Iterator
,因为它们有奇怪的有状态行为(更喜欢Iterable
)。但是,假设你有一个合理的,非过早的理由这样做,我首选的写作方式是
public Iterator<Foo> iterator() {
return getUnderlyingData().iterator();
}
private List<Foo> getUnderlyingData() {
if (underlyingData == null) {
return Collections.emptyList();
} else {
return underlyingData;
}
}
IMO,如果可以推断,最好不要插入可推断类型信息(即使它使你的代码更长)。
您几乎肯定会多次执行此操作,因此请插入getUnderlyingData
方法,而不是仅声明局部变量。
你在两个结果上都在调用iterator
,所以不要重复。
答案 5 :(得分:0)
抱歉,我明白了。您需要使用赋值,以便编译器可以找出参数化类型。
public Iterator<Foo> iterator() {
if (underlyingData != null) {
return underlyingData.iterator();
} else {
List<Foo> empty = Collections.emptyList(); // param type inference
return empty.iterator();
}
}
答案 6 :(得分:0)
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(){
}
}
}