1
votes

Générique en Java générant des erreurs lorsque des méthodes sont définies

J'apprends les génériques en Java. Pour cela, j'ai essayé une simple LinkedList comme ça.

LinkedList.java:16: error: cannot find symbol
      current.setNext(x);
             ^
  symbol:   method setNext(T)
  location: variable current of type T
  where T is a type-variable:
    T extends Object declared in class LinkedList
LinkedList.java:24: error: cannot find symbol
      ptr = ptr.getNext();
               ^
  symbol:   method getNext()
  location: variable ptr of type T
  where T is a type-variable:
    T extends Object declared in class LinkedList
2 errors

Mais j'obtiens cette erreur, alors que toutes les méthodes existent dans la classe Node. Quelle erreur est-ce que je fais?

class Node {
  private int age;
  private String name;
  private Node next;

  public Node(int age, String name) {
    this.age = age;
    this.name = name;
    this.next = null;
  }

  public int getAge() {
    return this.age;
  }

  public String getName() {
    return this.name;
  }

  public Node getNext() {
    return this.next;
  }

  public void setNext(Node next) {
    this.next = next;
  }
}

class LinkedList<T> {
  private T head;
  private T current;

  public LinkedList() {
    head = null;
    current = null;
  }

  public void append(T x) {
    if (head == null) {
      head = x;
      current = x;
    }
    else {
      current.setNext(x);
      current = x;
    }
  }

  public T getAt(int index) {
    T ptr = head;
    for(int i = 0; i < index; i++) {
      ptr = ptr.getNext();
    }
    return ptr;
  }
}

class Main {
  public static void main(String[] args) {
    LinkedList<Node> list = new LinkedList<Node>();
    list.append(new Node(39, "John"));
    list.append(new Node(43, "Josh"));
    Node x = list.getAt(1);
    System.out.println(String.format("%d, %s", x.getAge(), x.getName()));
  }
}


0 commentaires

5 Réponses :


1
votes

Si current est de type T , vous ne pouvez pas appeler les méthodes de la classe Node (comme setNext () ) sur current , car T peut être remplacé par n'importe quelle classe lorsque vous instanciez votre LinkedList .

Votre La classe Node ne doit pas être l'argument de type générique de LinkedList . Une LinkedList doit toujours être constituée de Node s. Le type des données stockées dans chaque Node doit être un type générique.

class LinkedList<T> {
  private Node<T> head;
  private Node<T> current;
}

Et la LinkedList doit contenir Nœuds nœuds:

class Node<T> {
  private T data;
  private Node next;

  public Node(T data) {
    this.data = data;
    this.next = null;
  }
}


2 commentaires

OK, c'est la méthode préférée bien sûr, mais pourquoi ai-je des erreurs dans ce code? Je n'y vois rien de mal.


@MetallicPriest vous essayez d'appeler une méthode de la classe Node sur une instance dont le type est le paramètre de type générique T . C'est faux.



0
votes

Vous devez créer Node et LinkedList .

public void append(T x) { // Here x is of Type T
if (head == null) {
  head = x;
  current = x; //Assigning x to current, current is also of Type T
}
else {
  current.setNext(x); // T.setNext is not defined! Because T can be a String/Integer/whatever. They do not have setNext method
  current = x;
}
}


0 commentaires

1
votes

Le compilateur est incapable de comprendre le type T. Vous avez utilisé t.setNext () , mais il n'est pas présent dans la définition T sauf s'il est réellement utilisé. Cela peut sembler un peu déroutant ici, mais essayez ceci:

Créez un Contrat d'interface avec les méthodes setNext et getNext. Implémentez Node qui s'étend au-dessus de l'interface. Node implémente le contrat . Dans la liste liée, remplacez les génériques par T étend le contrat


0 commentaires

1
votes

Il n'y a pas de hasNext pour un T générique donné, donc le code ne se compile pas

Vous devez vous assurer que la LinkedList ne contient que Node classes ou ses sous-types

class LinkedList<T> {
    Node<T> head;

Mais notez: ce T n'est pas le même que le générique stocké dans les nœuds, donc cela semble mieux

class LinkedList<T extends Node>


0 commentaires

1
votes

private T current; est un type générique et vous appelez setNext et getNext dessus. Comment se fait-il que T sache qu'il a toujours ces méthodes? C'est la raison pour laquelle cela ne fonctionne pas.

Par conséquent, vous devez vous assurer que votre type générique T sait qu'il a les méthodes setNext et getNext .

Par conséquent, le correctif est:

T étend NodeAbstract dans la définition de classe où NodeAbstract est l'interface déclarant la signature de ces méthodes. maintenant cela garantit que tout ce que T obtient aura toujours ces deux méthodes.


0 commentaires