Node( T itemArg, Node<T> nextArg ) {
this.item = itemArg;
this.next = nextArg;
}
Is this the right way to represent generic constructor
This is correct, as long as the parameter is specified in the class definition.
EDIT: Ensure item is an instance of T, and next is an instance of Node<T>.
public class Node<T> {
T item;
Node<T> next;
//your constructor
}
Related
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
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 Nodes. 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;
}
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
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;
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.
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;
}
}
I am trying to understand the way, how interface works. After doing some research, I found that interfaces are used to specify what a class must do.
I implemented a method(first())in outer class which will return element of Position<E> instance, but the main point where I get confused is, first() uses a method getNext() from Node class which returns Node<E> object, so why I am able to return Position<E> object instead of Node<E> and I can even return Node<E> object from first() method.
private static class Node<E> implements Position<E> {// Inner Class
private E element;
Node<E> previous;
Node<E> next;
Node(E element, Node<E> previous, Node<E> next) {
this.element = element;
this.previous = previous;
this.next = next;
}
#Override
public E getElement() throws IllegalStateException {
if (next == null)
throw new IllegalStateException("Position no longer valid");
return element;
}
private Node<E> getNext() {
return next;
}
}
Outer class method
#Override
public Position<E> first() {
return header.getNext();
}
Since Node<E> implements Position<E>, each instance of Node<E> is also an instance of Position<E> (or, to be exact, an instance of a class that implements Position<E>).
Therefore you can return an instance of Node<E> in a method whose return type is Position<E>.
why I am able to return Position object instead of Node
Because, Node implements Position and that implies Node is a type of Position. So, Position can hold any class instance, who implemented it. In your case, it is Node class, referring to getNext method, which returns Node type object
private Node<E> getNext() {
return next;
}
So im getting this ClassCastException when trying to cast my Node<T> to my AVLNode<T>. No idea why.
Here is where it throws an exception.
Node<Integer> n1 = new Node<Integer>(3, null);
AVLNode<Integer> n2 = (AVLNode<Integer>) n1;
How the classes look...
public class Node<T extends Comparable<T>> {
public Node<T> right;
public Node<T> left;
public Node<T> parent;
public T data;
public Node(T data, Node<T> parent) {
this.data = data;
this.parent = parent;
} // ...
And the other class in separate file:
public class AVLNode<T extends Comparable<T>> extends Node<T> {
public int height = 1;
public AVLNode(T data, Node<T> parent) {
super(data, parent);
} //...
Error message:
Exception in thread "main" java.lang.ClassCastException: custom.trees.Node cannot be cast to custom.trees.AVLNode
Basically, because a Node is not a AVLNode - you created it a Node, so it's a Node. If you'd created it as a AVLNode you could cast it to a Node, but not the other way round.
Your node is a SuperClass of AVLNode. You have misunderstood how Java casting works,
you cannot make such casts as such. The only situation where you should cast is,
if you have a node reference that points to AVLnode Object, you can say
Node n1=new AVLNode();
AVLNode n2=(AVLNode)n1;
where, since the object type is the same, the reference can be casted.
What you are trying here is to cast a Node (parent class) Object's Reference to a AVLNode (Sub-Class) reference, which simply isn’t possible!
You are down casting Node to AVLNode. Since n1 is an instance of Node it does not contain the extra implementation provided by AVLNode and this is why you get the casting exception to prevent you from executing a method of AVLNode on a Node instance.
This question already has answers here:
Java error: Implicit super constructor is undefined for default constructor
(12 answers)
Closed 9 years ago.
Can anyone tell me why i get an error saying
Implicit super constructor Node() is undefined. Must explicitly
invoke another constructor
I am aware in some cases eclipse gives this error when there is a mix of Java compiler version with the code but this is not the case for me. Here is my code, and the error is in the Queue2 class at the Queue2 constructor.
import java.util.NoSuchElementException;
public class Queue2<T, Item> extends Node<T> {
private Node<T> head;
private Node<T> tail;
// good practice to initialize all variables!
public Queue2() {
head = null;
tail = null;
}
public void enqueue(T newData) {
// make a new node housing newData
Node<T> newNode = new Node<T>(newData);
// point _head to newNode if queue is empty
if (this.isEmpty()) {
_head = newNode;
}
// otherwise, set the current tail’s next
// pointer to the newNode
else {
_tail.setNext(newNode);
}
// and make _tail point to the newNode
_tail = newNode;
}
// in class Queue<Type> …
public Type dequeue() {
if (this.isEmpty()) {
return null;
}
// get _head’s data
Type returnData = _head.getData();
// let _head point to its next node
_head = _head.getNext();
// set _tail to null if we’ve dequeued the
// last node
if (_head == null){
_tail = null;
}
return returnData;
public boolean isEmpty() {
// our Queue is empty if _head
// is pointing to null!
return _head == null;
}
}
Here is the super class...and i realize getters and setters arent complete, but i believe that is irrelevant to my error? :S
public class Node<Type> {
private Type _data;
private Node<Type> _nextNode;
public Node(Type newData) {
_data = newData;
_nextNode = null;
}
public void setNext(Node<T> newNextNode){
}
public Node<Type> getNext() {
}
public Type getData() {
}
public void setData(Node<T> newData){
}
}
btw, this is just some code to do some queue practice!
Thanks in advance everyone!!!
I suspect the only constructor for Node<T> is like this:
public Node<T>(T value)
That makes complete sense - a node should have a value. Then your Queue2 constructor fails because this:
public Queue2() {
head = null;
tail = null;
}
is implicitly:
public Queue2() {
super(); // This is what's failing.
head = null;
tail = null;
}
What makes far less sense is for Queue2 to extend Node in the first place. Just use composition instead of inheritance. Why would you ever want to treat a queue as a node? What's the node value of a queue? What's the previous node? What's the next node?
The problem is that you have Queue2<T, Item> extends Node<T>, that you don't have a no-arg constructor for Node<T>, and that the constructor for Queue2<T, item> doesn't indicate which Node<T> constructor is supposed to be called.
I think you actually don't want Queue2<T, Item> to be a subclass of Node<T> (you have a has-a relationship, not an is-a relationship), so change this:
public class Queue2<T, Item> extends Node<T> {
to this:
public class Queue2<T, Item> {
When you create a class and do not define a constructor, Java define an implicit one for you, with no parameters (and that does nothing).
When this happen but that you inherit from another class (like Queue2 that inherit from Node), this implicit constructor will also call the parent class constructor, so an equivalent of :
public Queue2() {
super();
}
The error that you see is linked to the fact that the parent class has no default (no-parameters) constructor, so this "implicit" code cannot work.
To solve this, define a constructor yourself, passing any parameter required by the Node constructor. See the official doc on this.
Because You haven't default non-private constructor in Node class. You have to define default constructor in Node class or call another constructor of Node class from your Queue class
Or avoid this crazy solution cause Queue probably will keep Node objects, not derive from Node class
For a CS class I am writing a linked list implementation of a linked list interface created by my professor. The assignment requires us to use generics for the list. What I have created, I think, is pretty standard.
public class MyLinkedList<T> implements ADTListInterface {
...
private class Node<T> {
Node<T> head;
Node<T> prev;
public Node(int max) {
...
}
public void shift() {
...
Node<T> newNode = new Node<T>(this.max);
newNode.prev = head.prev;
...
}
}
...
}
At compile time following error is generated:
MyLinkedList.java:111: incompatible types
found : MyLinkedList<T>.Node<T>
required: MyLinkedList<T>.Node<T>
newNode.prev = head.prev;
This error has me very confused. Can anyone explain to me what the issue is?
Here is probably the problem:
private class Node<T> {
The <T> is causing extra problems. Because Node is an inner class, it doesn't need to declare its generic type again.
You should declare the Node class like below:
public class MyLinkedList<T> implements ADTListInterface {
...
private class Node {
Node head;
Node prev;
public Node(int max) {
...
}