Reputation: 30765
I am learning Generics in Java. For that, I tried out a simple LinkedList like that.
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()));
}
}
But I get this error, while all the methods do exist in the Node class. What mistake am I doing?
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
Upvotes: 1
Views: 421
Reputation: 7504
private T current;
is a generic type and you are calling setNext
and getNext
on it. How come T
know that it always have these methods? That's the reason it's not working.
Hence, you need to ensure that your generic type T knows that it has setNext
and getNext
methods.
Hence the fix is:
T extends NodeAbstract
in class definition where NodeAbstract is the interface declaring signature of these methods. now this ensures that anything T gets is always going to have these two methods.
Upvotes: 1
Reputation: 191743
There is no hasNext
for any given generic T
, so the code doesn't compile
You'd have to make sure that the LinkedList only holds Node classes or its subtypes
class LinkedList<T extends Node>
But note: That T is not the same as the generic stored within the nodes, so this seems better
class LinkedList<T> {
Node<T> head;
Upvotes: 1
Reputation: 142
Compiler is unable to understand T type. You have used t.setNext()
, however it is isn't present in T definition unless actually used. I might sound a bit confusing here but try this:
Create an Interface Contract
having setNext and getNext method.
Implement Node extending above interface. Node implements Contract
.
In Linked List change generics to T extends Contract
Upvotes: 1
Reputation: 393811
If current
is of type T
, you can't call methods of the Node
class (such as setNext()
) on current
, since T
can be substituted by any class when you instantiate your LinkedList
.
Your Node
class shouldn't be the generic type argument of LinkedList
. A LinkedList
should always be made of Node
s. The type of the data stored in each Node
should be a generic type.
class Node<T> {
private T data;
private Node next;
public Node(T data) {
this.data = data;
this.next = null;
}
}
And the LinkedList
should contain Node<T>
nodes:
class LinkedList<T> {
private Node<T> head;
private Node<T> current;
}
Upvotes: 1
Reputation: 4591
You must make Node<T>
and LinkedList<Node>
.
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;
}
}
Upvotes: 0