我正在尝试编写一个泛型方法来返回数组形式的Iterable内容。
这就是我所拥有的:
public class IterableHelp
{
public <T> T[] toArray(Iterable<T> elements)
{
ArrayList<T> arrayElements = new ArrayList<T>();
for(T element : elements)
{
arrayElements.add(element);
}
return (T[])arrayElements.toArray();
}
}
但我收到编译器警告'注意:... \ IterableHelp.java使用未经检查或不安全的操作。'
关于另一种避免这种警告的方法的想法?
答案 0 :(得分:27)
Google Guava中有一种方法Iterables.toArray
。
查看the source,其定义为:
/**
* Copies an iterable's elements into an array.
*
* @param iterable the iterable to copy
* @param type the type of the elements
* @return a newly-allocated array into which all the elements of the iterable
* have been copied
*/
public static <T> T[] toArray(Iterable<? extends T> iterable, Class<T> type) {
Collection<? extends T> collection = toCollection(iterable);
T[] array = ObjectArrays.newArray(type, collection.size());
return collection.toArray(array);
}
ObjectArrays.newArray
最终委托给一个看似如下的方法:
/**
* Returns a new array of the given length with the specified component type.
*
* @param type the component type
* @param length the length of the new array
*/
@SuppressWarnings("unchecked")
static <T> T[] newArray(Class<T> type, int length) {
return (T[]) Array.newInstance(type, length);
}
所以看起来没有办法完全避免@SuppressWarnings
,但你可以而且至少应该将它限制在尽可能小的范围内。
或者,更好的是,只使用其他人的实现!
答案 1 :(得分:2)
没有办法摆脱unchecked or unsafe operations
警告,或者在不编辑方法签名的情况下创建TypeSafe数组。
有关详细信息,请参阅此bug report。
一种方法是传入预先分配的类型为T
的数组:
public class IterableHelp
{
public <T> T[] toArray(final T[] t, final Iterable<T> elements)
{
int i = 0;
for (final T element : elements)
{
t[i] = element;
}
return t;
}
}
这消除了unchecked or unsafe
警告,但它也将责任放在调用类上,以创建具有正确边界的数组,以便以哪种方式破坏了方便方法的目的。
如果要动态创建TypeSafe数组,实际上无法在Java中以TypeSafe方式执行此操作。
这可以工作和编译,但它无法解决未检查或不安全强制转换问题,只是将其移动到其他位置。我必须添加@SuppressWarnings
注释才能让它停止抱怨演员。
@SuppressWarnings({"unchecked"})
public class IterableHelp
{
public <T> T[] toArray(Class<T> t, Iterable<T> elements)
{
final ArrayList<T> arrayElements = new ArrayList<T>();
for (T element : elements)
{
arrayElements.add(element);
}
final T[] ta = (T[]) Array.newInstance(t, arrayElements.size());
return arrayElements.toArray(ta);
}
}
答案 2 :(得分:0)
你遇到的问题比未经检查的警告要大。实际上,如果T不是Object,它将在运行时抛出ClassCastException。
尝试String[] foo = IterableHelp.toArray(new ArrayList<String>());
简单地说,因为数组在运行时包含组件类型,所以要创建一个合适的T [],你必须将组件类作为另一个参数传入(作为T或T []本身的类,或作为一个对象T或T []),并使用反射来创建数组。采用参数的Collection
toArray()
方法的形式由于这个原因而接受T []对象。