Java:如何为`Collection`实现`toArray` [英] Java: how to implement `toArray` for `Collection`

查看:253
本文介绍了Java:如何为`Collection`实现`toArray`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我有:

  public< T& T [] toArray(T [] old){
T [] arr = Arrays.copyOf(old,old.length + size());
int i = old.length;
for(E obj:this){
arr [i] = old.getClass()。getComponentType()。cast(obj);
++ i;
}
return arr;
}

(请注意,这不遵循axtavt指出的合同。)



我收到此警告:

 从捕获#2的未选中的投射?到T 

这仍然是实现它的最好/最直接的方法吗?我能以某种方式编码它没有警告的方式吗?






编辑:我目前的解决方案。首先,我真的不想在 toArray 本身中有这样的警告。因此,我对这些小助手函数进行了编码(在此处阅读)讨论这些):

  @SuppressWarnings(unchecked)static< T&类< ;?延伸T> classOf(T obj){
return(Class< ;? extends T>)obj.getClass();
}

@SuppressWarnings(unchecked)static< T>类< ;?扩展T> classOf(T [] array){
return(Class< ;? extends T>)array.getClass()。getComponentType();
}

@SuppressWarnings(unchecked)static< T> T [] newArray(Class< T> clazz,int size){
return(T [])Array.newInstance(clazz,size);
}



现在,我的 toArray 实现类似:

  public< T& T [] toArray(T [] array){
int size = size();
if(array.length< size){
array = newArray(classOf(array),size);
} else if(array.length> size){
array [size] = null;
}

int i = 0;
for(E e:this){
array [i] = classOf(array).cast(e);
i ++;
}
return array;
}


解决方案


这仍然是实现它的最好/最直接的方法吗?


这不是Josh Bloch的做法。请查看 AbstractCollection#toArray() 。下面是JDK 1.6.0_22的相关性摘要。

  public< T& T [] toArray(T [] a){
//估计数组的大小;准备看到更多或更少的元素
int size = size();
T [] r = a.length> = size
? a
:(T [])Array.newInstance(a.getClass()。getComponentType(),size);
迭代器< E> it = iterator();

for(int i = 0; i if(!it.hasNext()){//少于预期的元素
if (a!= r)
return Arrays.copyOf(r,i);
r [i] = null; // null-terminate
return r;
}
r [i] =(T)it.next();
}
return it.hasNext()? finishToArray(r,it):r;
}

源代码位于 src.zip 文件的JDK。你可以将它集成到任何象Eclipse / IDEA / Netbeans这样的IDE,以便你可以看到它,当你打开 AbstractCollection 类。


我可以用某种方式编码它没有警告吗?


否。

如果是打扰您,请使用 @SuppressWarnings(unchecked)扩展 AbstractCollection 而不是实现集合(如果可能),以便至少已经为您实现的基本功能。 p>

Right now, I have:

    public <T> T[] toArray(T[] old) {
        T[] arr = Arrays.copyOf(old, old.length + size());
        int i = old.length;
        for(E obj : this) {
            arr[i] = old.getClass().getComponentType().cast(obj);
            ++i;
        }
        return arr;
    }

(Note that this does not follow the contract as it was pointed out by axtavt.)

where I get this warning:

Type safety: Unchecked cast from capture#2-of ? to T

Is this still the best / most straightforward way to implement it? Can I somehow code it in a way without that warning? How would I implement it otherwise?


Edit: My current solution. First, I really wanted to not have such a warning in toArray itself. Therefore, I coded these little helper functions (read here for a further discussion about these):

@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T obj) {
    return (Class<? extends T>) obj.getClass();
}

@SuppressWarnings("unchecked") static <T> Class<? extends T> classOf(T[] array) {
    return (Class<? extends T>) array.getClass().getComponentType();
}

@SuppressWarnings("unchecked") static <T> T[] newArray(Class<T> clazz, int size) {
    return (T[]) Array.newInstance(clazz, size);
}   

Now, my toArray implementation looks like:

    public <T> T[] toArray(T[] array) { 
        int size = size();
        if (array.length < size) { 
            array = newArray(classOf(array), size);
        } else if (array.length > size) {
            array[size] = null;
        }

        int i = 0;
        for (E e : this) {
            array[i] = classOf(array).cast(e);
            i++;
        }
        return array;
    } 

解决方案

Is this still the best / most straightforward way to implement it? How would I implement it otherwise?

It's not how Josh Bloch did. Have a look at the source of AbstractCollection#toArray(). Here's an extract of relevance from JDK 1.6.0_22.

public <T> T[] toArray(T[] a) {
    // Estimate size of array; be prepared to see more or fewer elements
    int size = size();
    T[] r = a.length >= size 
        ? a 
        : (T[]) Array.newInstance(a.getClass().getComponentType(), size);
    Iterator<E> it = iterator();

    for (int i = 0; i < r.length; i++) {
        if (!it.hasNext()) { // fewer elements than expected
            if (a != r)
                return Arrays.copyOf(r, i);
            r[i] = null; // null-terminate
            return r;
        }
        r[i] = (T) it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}

The source code is available in src.zip file of the JDK. You can integrate it in any decent IDE like Eclipse/IDEA/Netbeans so that you can see it when you open the AbstractCollection class.

Can I somehow code it in a way without that warning?

No. Use @SuppressWarnings("unchecked") if it is bothering you.

That said, I'd suggest to extend AbstractCollection instead of implementing Collection if possible so that you have at least the basic features already implemented for you.

这篇关于Java:如何为`Collection`实现`toArray`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆