2016-04-25 58 views
6

Informazioni su iteratori Java e strutture generali di dati tramite i compiti.Perché l'errore javac "(x) non può essere applicato a (y)", si verifica quando i parametri e gli argomenti coincidono? (metodo di classe esterna che chiama classe esterna)

Ho creato un elenco doppiamente collegato (LinkedList) che utilizza Nodi (LinkedList $ Node) e ha un Iterator (LinkedList $ LinkedListIterator) Tutte le classi fanno uso di generici.

All'interno di LinkedListIterator @Overridden metodo remove() sto facendo uso di un metodo della classe esterna, vale a dire la classe LinkedList.

ottengo il seguente errore di compilazione:

./LinkedList.java:170: deleteNode(LinkedList<T>.Node<T>,LinkedList<T>.Node<T>,LinkedList<T>.Node<T>) in LinkedList<T> cannot be applied to (LinkedList<T>.Node<T>,LinkedList<T>.Node<T>,LinkedList<T>.Node<T>) 
     deleteNode(nodeToBeRemoved, next, prev); 

mio (primitiva) comprensione è che i tipi non corrispondono, però non riesco a vedere come le cose stanno così.

Ecco il mio codice di classe completo:

import java.util.Iterator; 
import java.util.NoSuchElementException; 
import java.util.ConcurrentModificationException; 


public class LinkedList<T> implements Iterable<T> { 
    private Node<T> sentinel; 
    private long modCount; //apparently no unsigned int's in Java. 

    public LinkedList() { 
     modCount = 0; 
     sentinel = new Node<T>(null); 
     sentinel.setNext(sentinel); 
     sentinel.setPrev(sentinel); 
    } 

    public void append(T t) { 
     /* 
        APPEND: 
         ... 
        [-----] 
        |  | 
        [-1st-] 
        |  | 
     inFront-> [SENTL] 
        |  | <-- [newNode] 
     behind--> [-----] 
        |  | 
        [-----] 
         ... 
     */ 
     Node<T> newNode = new Node<T>(t); 
     Node<T> inFront = sentinel; 
     Node<T> behind = sentinel.prev(); 

     //now actually insert: 
     insertNode(newNode, inFront, behind); 
    } 

    public void prepend(T t) { 
     /* 
        PREPEND: 
         ... 
        [-----] 
        |  | 
     inFront-> [-1st-] 
        |  | <-- [newNode] 
     behind--> [SENTL] 
        |  | 
        [-----] 
        |  | 
        [-----] 
     */ 

     Node<T> newNode = new Node<T>(t); 
     Node<T> behind = sentinel; 
     Node<T> inFront = sentinel.next(); 

     //now actually insert: 
     insertNode(newNode, inFront, behind); 
    } 

    public void removeHead() { 
     /* 
        REMOVE-FIRST: 
         ... 
     inFront --> [-----] 
        |  | 
        [-1st-] <-- *delete* 
        |  | 
     behind ---> [SENTL] 
        |  | 
        [-----] 
        |  | 
        [-----] 
         ... 
     */ 

     Node<T> inFront = sentinel.next().next(); 
     Node<T> behind = sentinel; 
     Node<T> toDelete = sentinel.next(); 

     // now actually delete 
     deleteNode(toDelete, inFront, behind); 
    } 

    private void insertNode(Node<T> newNode, Node<T> inFront, Node<T> behind) { 
     newNode.setNext(inFront); 
     newNode.setPrev(behind); 
     inFront.setPrev(newNode); 
     behind.setNext(newNode); 
     modCount++; 
    } 

    private void deleteNode(Node<T> toDelete, Node<T> inFront, Node<T> behind) { 
     inFront.setPrev(behind); 
     behind.setNext(inFront); 
     toDelete.setNext(null); 
     toDelete.setPrev(null); 
     modCount++; 
    } 

    @Override 
    public Iterator<T> iterator() { 
     return new LinkedListIterator<T>(sentinel); 
    } 






    /* 
     ..:: MyIterator ::.. 
     private inner class 
    */ 
    public class LinkedListIterator<T> implements Iterator<T> { 
     private Node<T> cursor; 
     private Node<T> lastReturned; 
     private long iterModCountPerspective; 

     public LinkedListIterator(Node<T> sentinel) { 
      cursor = sentinel.next(); 
      lastReturned = null; 
      iterModCountPerspective = modCount; 
     } 

     private boolean hasBodhi() { 
      // bodhi: in Buddhism, bodhi is the understanding of the "true nature of things". 
      return (iterModCountPerspective == modCount); 
     } 

     @Override 
     public boolean hasNext() { 
      if (cursor == sentinel) 
       return false; 
      return true; 
     } 

     @Override 
     public T next() { 
      if (!this.hasNext()) { 
       throw new NoSuchElementException(); 
      } else if (!hasBodhi()) { 
       throw new ConcurrentModificationException(); 
      } else { 
       T aux = cursor.data(); 
       lastReturned = cursor; 
       cursor = cursor.next(); 
       return aux; 
      } 
     } 

     @Override 
     public void remove() { 
      //check we're allowed to remove: 
      if (lastReturned == null) { 
       throw new IllegalStateException(); 
      } 
      if (!hasBodhi()) { 
       throw new ConcurrentModificationException(); 
      } 

      //setup vars to perform deletion: 
      Node<T> nodeToBeRemoved = lastReturned; 
      Node<T> next = nodeToBeRemoved.next(); 
      Node<T> prev = nodeToBeRemoved.prev(); 

      // now delete 
      deleteNode(nodeToBeRemoved, next, prev); 
      iterModCountPerspective++; 

      //now setup vars for exit: 
      cursor = next; 
      lastReturned = null; // illegal to remove yet-again before first calling next() 
     } 
    } 





    /*   ..:: Node ::.. 
     private, compositional inner class 

     Interface: 
     void  setNext(Node n) // change the Node in front of this Node 
     void  setPrev(Node p) // change the Node behind this Node 
     Node  next()   // returns the Node in front of this Node 
     Node  prev()   // returns the Node behind this Node 
     T  data()   // returns the data stored inside this Node 
    */ 
    private class Node<T> { 
     private T data; 
     private Node<T> next; 
     private Node<T> prev; 

     public Node(T d) { 
      data = d; 
      next = null; 
      prev = null; 
     } 

     /* 
      METHOD setNext(Node<T> n) 

       This method takes the parameter Node 
       passed-in and puts it in front of this 
       Node. 

       input - Node n 
       output - none 

       eg: node4.setNext(node5); 
      */ 
     public void setNext(Node<T> n) { 
      next = n; 
     } 


     /* 
      METHOD setPrev(Node<T> n) 

       This method takes the parameter Node 
       passed-in and puts it behind of this 
       Node. 

       input - Node p 
       output - none 

       eg: node5.setPrev(node4); 
      */ 
     public void setPrev(Node<T> p) { 
      prev = p; 
     } 



     /* 
      METHOD next() 

       This method returns the Node in 
       front of this Node. 

       input - none 
       output - Node infront of this (this.next) 

       eg: Node nodeInFrontOfNode4 = node4.next(); 
      */ 
     public Node<T> next() { 
      return next; 
     } 



     /* 
      METHOD prev() 

       This method returns the Node 
       behind of this Node. 

       input - none 
       output - Node behind of this (this.prev) 

       eg: Node nodeBehindOfNode4 = node4.prev(); 
      */ 
     public Node<T> prev() { 
      return prev; 
     } 



     /* 
      METHOD data() 

       This method returns the data 
       inside of this Node. 

       input - none 
       output - Data inside of this Node 

       eg: PlanarShape shape4 = node4.data(); 
      */ 
     public T data() { 
      return data; 
     } 
    } 

} 

studente Comp-sci, manifesto prima volta. Grazie a tutti i SO guru. Hai aiutato i miei colleghi e io molte volte

+1

Benvenuti in StackOverflow! La descrizione della tua domanda è molto chiara, tuttavia hai anche inserito una grande quantità di codice. La prossima volta, prova a restringere il codice a un esempio minimo che causerà lo stesso problema. –

+2

In genere ciò significa che hai due cose che sono effettivamente diverse ma che hanno lo stesso nome. In questo caso, a colpo d'occhio, posso vedere che non dovrebbe essere 'classe privata Nodo ' ma 'Nodo classe privata'. –

+3

Analogamente, 'publicListListIterator di classe pubblica implementa Iterator ' dovrebbe essere 'publicListListIterator di classe pubblica implementa Iterator '. Attualmente stai definendo un nuovo tipo generico su entrambe le classi 'LinkedListIterator' e' Node'.Si noti che anche se si usa 'T', tutti e tre i' T's' (incluso quello in 'LinkedList ') sono diversi. –

risposta

2

Questo sta accadendo, perché stai definendo 3 diversi parametri di tipo lì. Ogni volta che si dichiara una classe come:

class X<T> {} 

... si definisce un nuovo parametro di tipo T, se tale è una classe interna o di classe esterna. Così, nello scenario di seguito:

class X<T> { 
    class Y<T> { 
    } 
} 

sia il T's sono diversi. Si può fare qualcosa di simile:

X<String> x = new X<String>(); 
Y<Double> y = x.new Y<Double>(); 

Quindi, prendere in considerazione un caso qui:

class X<T> { 
    public void helloThere(T obj) { } 

    class Y<T> { 
     // Ignore any syntactical error about method calling. 
     public void callHelloThere(T obj) { 
      helloThere(obj); 
     } 
    } 
} 

che di certo non funziona per:

y.callHelloThere(2.5); 

Perché allora, si passa un Double digitare su un metodo che accetta uno String, poiché l'istanza è stata X<String>.

Questo è lo stesso scenario che stai affrontando nel tuo esempio.

Soluzione? Cambia class Y<T> a class Y e tutto è pronto.

+1

Bello, non sapevo che 'T! = T' – Antoniossss

+1

La mia comprensione dei generici è sotto-par. Grazie, Rohit. Risposta molto concisa e un grande esempio. –