2016-04-27 203 views
1

我的編譯器是JDK 6.0_65,和下面是我的代碼(Deque.java):在Java中,爲什麼在內部類上使用泛型不起作用?

import java.util.Iterator; 
public class Deque<Item> implements Iterable<Item> { 
    private Node first; 
    private Node last; 

    private class Node { 
     Item value; 
     Node next;   
    } 

    public Deque(){}     // construct an empty deque 

    public Iterator<Item> iterator() { 
     // return an iterator over items in order from front to end 
     return new DequeIterator<Item>(); 
    } 

    private class DequeIterator<Item> implements Iterator<Item> { 
     private Node current = first; 
     public boolean hasNext() { 
      return current.next != null; 
     } 
     public Item next() { 
      Item item = current.value; 
      current = current.next; 
      return item; 
     } 
     public void remove() {} 

    } 
    public static void main(String[] args) {   
     // unit testing 
     Deque<Integer> dq = new Deque<Integer>(); 

    } 

} 

在外部範圍:

public class Deque<Item> implements Iterable<Item> { 

被使用。

而在內部範圍:

private class DequeIterator<Item> implements Iterator<Item> { 

被使用。

DequeIterator的範圍內。我預計本地範圍(內部類範圍)Item將影響類範圍ItemDeque<Item>

然而,編譯階段期間,javac會拋出這樣的錯誤:

Deque.java:2: error: incompatible types 
      Item item = current.value; 
          ^
    required: Item#2 
    found: Item#1 
    where Item#1,Item#2 are type-variables: 
    Item#1 extends Object declared in class Deque 
    Item#2 extends Object declared in class Deque.DequeIterator 

它說Item#2Item#1是不兼容的類型,它看起來相當混亂給我,因爲我已經通過了類型參數ItemDequeIterator使用new DequeIterator<Item>()

有沒有人有這方面的想法?

+0

'Deque'是已經使用的JDK類名(當然,界面) ;這是不是一個很好的主意,重用... – fge

+2

就像節點沒有參數化(新)項目不在這裏引入一個新的項目,或重命名它。從那裏的DequeueIterator中刪除''。 –

回答

6

我預計本地範圍(內部類範圍)Item將遮蔽類範圍的項目從Deque<Item>

這基本上正是發生了 - 內範圍Item陰影外一。不要緊,你已經通過外部Item到構造函數。內部類在編譯時遇到問題,因爲您試圖將類型爲outer-Item的值分配給類型爲inner-Item的變量。

爲了解決這個問題只是讓嵌套類非通用:

private class DequeIterator implements Iterator<Item> 

這樣一來,您將使用outer- Item不宣,你真的不需要另一個Item類型參數。

0

試試這個,你甚至可以去除<T>

private class DequeIterator<T> implements Iterator<Item> { 
    ... 
} 

我認爲這個問題是某種在內部和外部Item被認爲是不同的陰影問題。

3

是內部類通用Item陰影泛型封閉類Item,這正是編譯器抱怨的原因。你寫了Item item=current.value(這就是問題所在)。這裏的Item是指內部類的通用類型,但current.value是封閉類的通用類型Item。這些類型是不同的!編譯器將它們命名爲Item#1Item#2。你只需要從內部類DequeIterator刪除通用性:

public class Deque<Item> implements Iterable<Item> { 
    private static class DequeIterator implements Iterator<Item> { 
    } 
} 
1

有沒有保證Item#1Item#2始終是相同的。你可以像這樣的方法添加到Deque

public Iterator<Integer> boom() { 
    return new DequeIterator<Integer>(); 
} 

這顯然沒有任何意義,但由於迭代器類的Item s的不相關的封裝類Item S(因爲內部Item類型參數影響外部)它是完全合法的。

沒有理由讓你給DequeIterator類的類型參數,雖然,你可以簡單地這樣聲明它:

private class DequeIterator implements Iterator<Item> { 
    // Content remains unchanged 
} 
相關問題