4

我想知道一个类的泛型类型是否可以由作为参数传递的另一个对象的泛型类型来定义?

我正在研究的是一个线程安全的迭代器,因此多个线程可以安全地迭代一个列表,而没有两个线程获得相同的对象。它以目前的形式运作良好,但我认为它可以做得更好。

import java.util.Iterator;
public class AtomicIterator implements Iterator<Object>
{
    private Iterator<?> it;

    public AtomicIterator(Iterable<?> iterable)
    {
        it = iterable.iterator();
    }

    public Object next()
    {
        synchronized(it)
        {
            if(it.hasNext())
                return it.next();
            else
                return null;
        }
    }
}

一些代码已被省略,但这应该可以理解。目前要获得下一个对象,您总是被迫转换返回的对象,这似乎效率低下。

ArrayList<String> someList = new ArrayList<String>;
AtomicIterator it = new AtomicIterator(someList);
String example = (String)it.next();

问题显然是在我想要的地方it.next()返回类型Object,在这个例子中,它返回类型String

简单的解决方案是给AtomicIterator它自己的泛型类型,结果是这样的

ArrayList<String> someList = new ArrayList<String>();
AtomicIterator<String> it = new AtomicIterator<String>(someList);
String example = it.next();

然而,这对我来说似乎是多余的,someList已经明确定义了它的泛型类型String,我想要的是从给它的对象中AtomicIterator推断出它的泛型类型。Iterable

我真正想要的是这样的

import java.util.Iterator;
public class AtomicIterator implements Iterator<E>
{
    private Iterator<E> it;

    public <E> AtomicIterator(Iterable<E> iterable)
    {
        it = iterable.iterator();
    }

    public E next()
    {
        synchronized(it)
        {
            if(it.hasNext())
                return it.next();
            else
                return null;
        }
    }
}

从那里可以做类似的事情

ArrayList<String> someList = new ArrayList<String>();
AtomicIterator it = new AtomicIterator(someList);
String example = it.next();

但这不起作用,因为泛型类型E只存在于构造函数的范围内。

有谁知道一个干净的方法来做到这一点?

4

3 回答 3

6

将泛型类型添加到 AtomicIterator,以及(如果在 Java 6 下运行)静态工厂方法,因此它默认解析泛型类型

public class AtomicIterator<T> implements Iterator<T>
{
    private Iterator<T> it;

    public AtomicIterator(Iterable<T> iterable)
    {
        it = iterable.iterator();
    }

    public static <T> AtomicIterator<T> create ( Iterable<T> iterable )
    {
        return new AtomicIterator( iterable )
    }

    public T next()
    {
        synchronized(it)
        {
            if(it.hasNext())
                return it.next();
            else
                return null;
        }
    }
}

这是用法:

ArrayList<String> someList = new ArrayList<String>;
AtomicIterator<String> it = AtomicIterator.create(someList);
于 2013-04-04T21:00:06.423 回答
0

泛型的问题AtomicIterator在于构造函数本身是泛型的,并且具有与类的泛型类型参数不同的泛型类型。<E>in定义了与类泛型参数不同的public <E> AtomicIterator泛型参数,即使两者都是E. 在我最初尝试编译它时,我得到了一个相当混乱的错误:

AtomicIterator.java:8: incompatible types
found   : java.util.Iterator<E>
required: java.util.Iterator<E>
        it = iterable.iterator();
                              ^

解决方法:让构造函数的泛型参数Iterable<E>使用类的泛型参数'E',方法是去掉<E>后面的 frompublic并将其添加到类中,因此泛型类型的范围E是整个类:

public class AtomicIterator<E> implements Iterator<E>
//                          ^ Added here

...

public AtomicIterator(Iterable<E> iterable)
//    ^ Remove here
于 2013-04-04T21:08:15.627 回答
0

Java 7 钻石推理 -

AtomicIterator<String> it = new AtomicIterator<>(someList); 
                                               ^ 
                                               no need to repeat String here


public class AtomicIterator<E> implements Iterator<E>

    public AtomicIterator(Iterable<E> iterable)

如果您不想显式编写 的完整类型it,请让编译器推断类型,例如

var it = new ...;   // the type of `it` is inferred from right hand side

不幸的是,Java 还没有这个特性,而且暂时不会有。

于 2013-04-04T21:21:29.600 回答