2016-10-29 5 views
0

どのような状況でジェネリックスを使うべきか理解したい。Iterableを実装したLinkedListでGenericを使用する

iterableであるLinkedListを実装したいとします。

実装1:

public class LinkedList<E>{ 
    private Node head; 

    private class Node{ 
     private Node next; 
     private E e; 
    } 
} 

私の最初の質問:明らかに、LinkedListのは一般的なものの型パラメータを持つべきノードも持つべき型パラメータEを?

実装2:

public class LinkedList<E>{ 
    private Node<E> head; 

    private class Node<E>{ 
     private Node<E> next; 
     private E e; 
    } 
} 

両方の実装が微細コンパイルすなわち、上記のコードは次のように書かれるべきです。私は私の教科書に実装1を見ました。したがって、実装2は少し不必要なようです。

次に、Iterableを実装したいと思います。我々が実装1に固執すると仮定し、我々が持っているでしょう:

実装3:

public class LinkedList<E> implements Iterable<E>{ 
private Node head; 

private class Node{ 
    private Node next; 
    private E e; 
} 

public Iterator<E> iterator(){ 
    return new LinkedListIterator(); 
} 

private class LinkedListIterator implements Iterator<E>{ 
    private Node curr; 

    public boolean hasNext(){ 
     return curr != null; 
    } 
    public E next(){ 
     E element = curr.e; 
     curr = curr.next; 
     return element; 
    } 
}  

これは私が教科書で見てきた実装の標準一種です。

私の2番目の質問:ノードにジェネリック型がないため、イテレータとイテレータにジェネリック型を使用できないのはなぜですか?例えば:

実装4:

public class LinkedList1<E> implements Iterable{ 
    private Node head; 

    private class Node{ 
     private Node next; 
     private E e; 
    } 

    public Iterator iterator(){ 
     return new LinkedListIterator(); 
    } 

    private class LinkedListIterator implements Iterator{ 
     private Node curr = head; 

     public boolean hasNext(){ 
      return curr != null; 
     } 
     public E next(){ 
      E element = curr.e; 
      curr = curr.next; 
      return element; 
     } 
    }  
} 

答えて

2

最初の質問:あなたは完全に正しい、内部Nodeクラスのジェネリックを使用することは不要です。これは、NodeLinkedList<E>の一部であるため、すでに暗黙的に一般的なので、それ以上のことは必要ありません。 NodeクラスがLinkedList以外の別のクラスになっていた場合は、それを汎用化する必要がありました。

EDIT:少し具体的に見ると、Nodeクラスは実際にはLinkedList<E>の各インスタンスに属しています。 2つのリンクリストがある場合、list1.Nodelist2.Nodeは同じクラスと見なされません(list1.headlist2,headは同じ変数ではありません)。 list1list2の要素の種類が同じか異なるかどうかは関係ありません。しかし、それはNodeはすでに型パラメータEを持つオブジェクトに属していることを意味し、そしてあなたはあなただけ使用することができ、その場合には、それを再宣言しない限り、ENodeの内側には、あまりにも(新しくE宣言することを使用することができ、それがLinkedListE影が薄いです)。

静的宣言がLinkedListにある場合は、上記は実行されません。静的フィールドはすべてのインスタンスで共有されていることはすでに分かっています。 private static class Node …と宣言した場合、そのクラスはリンクされたすべてのリスト間で共有されます。ロジックは引き続き動作しますが、一般的であることを宣言しなければなりません(LinkedList以外のクラスとまったく同じです)。また、にpublic static void main()がある場合は、LinkedListであるにもかかわらず、それは静的ではないので、ここでLinkedListをインスタンス化すると、コメントに記載されているように、型パラメータを与える必要があります。編集の終わり。

2番目の質問:タイプパラメータをIterableIteratorインターフェイスに渡す必要があります。これはあなたのLinkedListクラスの外にあるため、クラスのジェネリックな性質によってカバーされていないからです。一方、非静的クラスLinkedListIteratorLinkedListの内部にあり、したがってLinkedListはそれ自体が汎用であると宣言する必要はないため、汎用です。

+0

「NodeはLinkedListの一部です」という意味は理解できません。 NodeとLinkedListIteratorはLinkedList の内部クラスですが、Iterableはそうではありません。私はNodeがどのように暗黙的に汎用的であるかはかなり分かりません。たとえば、LinkedList.javaのmainメソッドで、 "LinkedList ls = new LinkedList ();(文字列をlsに入れます); String str = ls.head.e;"が存在するとします。 「互換性のない型:ObjectをStringに変換できないため」コンパイル時エラー。 – Student