Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使Java Iterable从扩展泛型返回基子类型_Java_Generics_Iteration - Fatal编程技术网

如何使Java Iterable从扩展泛型返回基子类型

如何使Java Iterable从扩展泛型返回基子类型,java,generics,iteration,Java,Generics,Iteration,我试图使一个类的子类是可测试的。这与此类似。但是,我需要让列表中的对象是特定类的子类,例如下面示例中的QObject。此外,我需要迭代器来实现与ListIterator接口相关的特定方法 问题是实现ListIterator接口的内部类在实现中没有返回基泛型类型QObject。我使用QueueListIterator泛型的方式有问题 现在,如果我在我的示例代码中用Queue声明队列,它就会工作。这必须提供允许迭代器获得正确类型所需的信息。但是,即使基泛型类型是QObject,并且队列类中的其他方法

我试图使一个类的子类是可测试的。这与此类似。但是,我需要让列表中的对象是特定类的子类,例如下面示例中的QObject。此外,我需要迭代器来实现与ListIterator接口相关的特定方法

问题是实现ListIterator接口的内部类在实现中没有返回基泛型类型QObject。我使用QueueListIterator泛型的方式有问题

现在,如果我在我的示例代码中用Queue声明队列,它就会工作。这必须提供允许迭代器获得正确类型所需的信息。但是,即使基泛型类型是QObject,并且队列类中的其他方法使用基泛型类型,但仅将其声明为Queue并不会这样做

所以,我的问题是为什么会发生这种情况,有没有办法指定QueueListIterator来识别基本泛型类型

    public class Queue<T extends QObject> implements Iterable<T> {
        /**
         * The list of items in the queue.
         */
        protected List<T> myList;

        // other methods and defs

        public final Iterator<T> iterator() {
            return (new QueueListIterator());
        }

        public final ListIterator<T> listIterator() {
            return (new QueueListIterator());
        }

        private class QueueListIterator implements ListIterator<T> {

            protected ListIterator<T> myIterator;

            protected QueueListIterator() {
                myIterator = myList.listIterator();
            }

            @Override
            public void add(T o) {
                throw new UnsupportedOperationException("The method add() is not supported for Queue iteration");
            }

            @Override
            public boolean hasNext() {
                return myIterator.hasNext();
            }

            @Override
            public boolean hasPrevious() {
                return myIterator.hasPrevious();
            }

            @Override
            public T next() {
                return myIterator.next();
            }

            @Override
            public int nextIndex() {
                return myIterator.nextIndex();
            }

            @Override
            public T previous() {
                return myIterator.previous();
            }

            @Override
            public int previousIndex() {
                return myIterator.previousIndex();
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("The method remove() is not supported for Queue iteration");
            }

            @Override
            public void set(T o) {
                throw new UnsupportedOperationException("The method set() is not supported for Queue iteration");
            }
        }
    }

    // testing code
    public static void test(){

            Queue q = new Queue();
            // put some stuff in the Queue
            QObject r1 = new QObject(q.getTime(), "A");
            q.enqueue(r1);
            QObject r2 = new QObject(q.getTime(), "B");
            q.enqueue(r2);

            // Does not work! 
            // incompatible object types, Object cannot be converted to QObject in the for( : ) construct
            for (QObject qo : q) {
                System.out.println(qo);
            }
    }

如果您这样声明q会怎么样: 队列q

使用原始类型队列与使用队列擦除相同。T removeFirst允许您检索QObject而不是Iterator.next的原因是T removeFirst和Iterator Iterator擦除方式不同。类型变量的擦除是对其最左边边界的擦除,因此T擦除到QObject,但参数化类型的擦除是没有任何类型参数的类型,因此迭代器擦除到迭代器

在使用原始类型时,没有办法得到这样的结果,您应该改用队列。在某些情况下,还可以将队列用作引用类型。看


也见

这是一个评论,而不是答案。我认为这是一个评论,而不是答案。我原来的帖子已经指出了这一点。我编辑了这个问题,因为我的第一篇帖子遗漏了LT和GT标志。是的,队列q提供了必要的类型信息。但是,我相信,如果我对获取QObject没有意见,那么在声明队列时就不必提供基本泛型类型。这只是泛型使用中的一个问题。应该是Queue q=new Queue。我知道队列可以工作。但是,如果我只是将队列声明为queue q=new queue,那么未显示的其他方法(如T removeFirst)将获得通用基类型QObject,而不从声明中提供它,因为它们知道类型T必须是QObject的子类型。但是,我不能得到迭代的方法来做同样的事情。根本没有办法做到这一点。但您不必担心,因为您无论如何都不应该使用没有类型参数的队列。Louis,我现在同意了。我现在必须进一步研究泛型类型系统。这是有帮助的,尽管令人失望。似乎有理由让我的内部类以我想要的方式知道基泛型类型。然而,理解不应该使用原始类型表明了我对类型系统的基本误解。现在清楚一点了。