我在将一个应用程序升级到Java 8时,在几个地方遇到了与Google Guava的newArrayList
相关的奇怪问题。
看看这个例子:
import com.google.common.collect.UnmodifiableIterator;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import java.util.ArrayList;
import static com.google.common.collect.Iterators.forEnumeration;
import static com.google.common.collect.Lists.newArrayList;
public class NewArrayListIssue {
public static void main(String[] args) throws NamingException {
UnmodifiableIterator<?> elements = forEnumeration(getEnumeration().getAll());
System.out.println("declarefirst = " + newArrayList(elements)); // calls newArrayList(Iterator<? extends E> elements)
ArrayList directCopy = newArrayList(forEnumeration(getEnumeration().getAll()));
System.out.println("useDirectly = " + directCopy); //calls newArrayList(E... elements)
}
public static Attribute getEnumeration(){
return new BasicAttribute("foo",1);
}
}
在第一个例子中,当我将UnmodifiableIterator
先存储到自己的变量中,然后调用newArrayList
时,得到了我期望的结果,即将迭代器的值复制到新的List
中。
在第二个例子中,当forEnumeration
直接进入newArrayList
方法时,返回的是一个包含迭代器(其中包含值)的List
。
根据Intellij的推测,两个方法调用都应该是newArrayList(Iterator<? extends E> elements)
,但我发现调试时第二个调用实际上进入了newArrayList(E... elements)
。
只有在使用针对Java8的Oracle JDK8编译时才会出现这种情况。如果我针对7进行编译,就能正常工作。
1.8.0_20
测试了一下,它产生了一个错误,但在beta版的1.8.0_40
中编译成功了。这是一致的:如果使用1.8.0_40
进行编译而没有删除varargs方法,则仍会调用正确的方法。 - Holger