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
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;
}
}
The abstract method getNextNode generates the error, "cannot make a static reference to the non-static type Node," but only if LinkedList is parameterized. If I remove the generic from LinkedList the error goes away. Why?
public class LinkedList<T> {
Node head;
public LinkedList() {
head = new Node();
}
private class Node {
}
interface stuff {
public Node getNextNode();//ERROR Cannot make a static reference to the non-static type Node
}
}
As the error is trying to tell you, you can't use a generic type without its parameter.
Node is actually LinkedList<T>.Node. Since your interface isn't generic (interfaces don't inherit type parameters from the containing class), there is no T it can substitute.
You can fix this by making the Node class static, so that it doesn't inherit the type parameter from its containing class.
However, you don't actually want to do that, since the Node should be generic.
You actually need to make your interface generic as well, so that it can specify a T.
The Node short for LinkedList<T>.Node and your getNextNode() doesn't know what T is.
interface can't be defined in an inner class
http://www.xyzws.com/javafaq/why-an-interface-cant-be-defined-in-an-inner-class/56
public class Test{
interface stuff {
public LinkedList.Node getNextNode();
}
public class LinkedList<T> {
Node head;
public LinkedList() {
head = new Node();
}
private class Node {
}
}
We seem to have a problem implementing the insert method that is given to us in the ListInterface. Can you help us with finding the right type to return?
//Method in class list:
public ListInterface insert(E d) {
Node c = new Node(d, null, current);
current.prior = c;
return ????;
}
public interface ListInterface<E extends Data<E>> extends Clonable<ListInterface<E>> {
}
private class Node{ // Inner class for the implementation of the List class.
E data;
Node prior,
next;
public Node(E d) {
this(d, null, null);
}
public Node(E data, Node prior, Node next) {
this.data = data == null ? null : data;
this.prior = prior;
this.next = next;
}
}
In Java, the return type is specified in the function declaration keywords
public ListInterface insert(E d) {
public, meaning accessible outside its class scope, followed by ListInterFace, which is the return type the function is expected to return. It could also be void, String, Double, etc, any datatype.
In this case, your function expects you to return a ListInferface object.
Somewhere in your insert function, you'll need to instantiate your return object, somewhere along the lines of:
ListInferfaceImplement x = new ListInterfaceImplement();
//do list stuff
return x;
Edit: you may not be instantiating that exact object (I believe comments say you can't instantiate an interface), but an object that implements this interface.
If you want Node to be returned by the insert method, you'll need to have the Node class implement the ListInterface
private class Node implements ListInterface {
It is very strange to return the list implementation after an item has been added to the list.
Preffered approach is a success/failure value - a boolean.
But if you want to proceed with this, then say you are writing the implementation for say LinkedList then,
class LinkedList extends ListInterface{
public ListInterface insert(E d) {
Node c = new Node(d, null, current);
current.prior = c;
return this;
}
}
It seems that the insert function is designed to allow for chaining. It will allow you to chain method calls together like so :
// For the sake of example, assume String implements Data<E>
// and that List<E> implements ListInterface<E>.
ListInterface<String> list = new List<>();
list.insert("a")
.insert("b")
.insert("c");
The idea is that in the end, all three Strings are added to the list. The insert function returns a ListInterface simply to allow this shorter syntax.
You want all these methods to insert elements to list, so you should make sure that your method returns itself:
public ListInterface insert(E d) {
Node c = new Node(d, null, current);
current.prior = c;
return this;
}
I'm trying to call a constructor for a generic abstract class within a method of said class. The code below shows this:
public abstract class Node<T> {
public Collection <Node<T>> pars;
public Collection<Node<T>> interactors;
private boolean target = false;
private boolean multiple = false;
private T value;
//constructor for a simple node
public Node(T val){
this.value = val;
}
//constructor for a multiple interaction node
public Node(Collection<Node<T>> inter, T val){
this.interactors = inter;
this.value = val;
if (inter.size()>0){
this.multiple = true;
}
}
public void find_inters(){
ArrayList<Collection<T>> multi_interactions = search();
for (int i = 0; i < multi_interactions.size(); i++){
Node<T> a = new Node<T>(multi_interactions.get(i), this.value); <----i get compile error here
}
}
}
but I keep getting an error that I can't instantiate type Node. I want to create a new Node object within the function find_inters() but I can't. Anyone know why/possible solutions?
You've said that Node is abstract because you can't yet implement some of the methods, but the problem is that you want Node<T> a to be a Node object, but you have to decide what a will actually do when you call those methods.
You can have classes that don't have all their methods implemented -- that's how abstract classes work -- but you can't have objects that don't have all their methods implemented, because that object can have that method called, and your program needs to know what to do.
What you can do is write Node<T> a = new MySubNode<T>(...), where MySubNode is a subclass of Node with all the methods filled in. Or you can write Node<T> a = new Node<T>(...) { implementations of methods go here }, which is essentially the same thing, except the implementation is in an anonymous class. But you can't instantiate an abstract class.
Just to add to Louis's answer. If search() is abstract, you can change it to return ArrayList<Node<T>>, so the implementing classes can do something like Node<T> a = new MySubNode<T>(...) (unless search() is used somewhere else that requires ArrayList<Collection<T>>).
I need to write a tree class in Java where each level has a unique object type. The way it is written below does not take advantage of generics and causes alot of duplicate code. Is there a way to write this with Generics ?
public class NodeB {
private String nodeValue;
//private List<NodeB> childNodes;
// constructors
// getters/setters
}
public class NodeA {
private String value;
private List<NodeB> childNodes;
// constructors
// getters/setters
}
public class Tree {
private String value;
private List<NodeA> childNodes;
// constructors
// tree methods
}
This is simplistic implementation, but enough to give general idea:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class GenericNode {
public static abstract class AbstractNode<V, N> {
private V value;
private List<N> children;
public AbstractNode(V value, N... children) {
this.value = value;
this.children = children != null ? Arrays.asList(children)
: Collections.<N> emptyList();
}
public V getValue() {
return value;
}
public List<N> getChildren() {
return children;
}
public int getNumberOfChildren() {
return children.size();
}
#Override
public String toString() {
return value.toString() + "->" + children.toString();
}
}
// leaf node type, ignore type of children
public static class NodeB extends AbstractNode<String, Object> {
public NodeB(String value, Object... nodes) {
super(value, nodes);
}
}
// example of typical node in the mid of tree
public static class NodeA extends AbstractNode<String, NodeB> {
public NodeA(String value, NodeB... nodes) {
super(value, nodes);
}
}
// top level node type
public static class Tree extends AbstractNode<String, NodeA> {
public Tree(String value, NodeA... nodes) {
super(value, nodes);
}
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public static <V, N extends AbstractNode> int getNodeCount(
AbstractNode<V, N> node) {
int nodeCount = node.getChildren().size();
for (N child : node.getChildren()) {
nodeCount += getNodeCount(child);
}
return nodeCount;
}
public static void main(String[] args) {
NodeB nodeB1 = new NodeB("Leaf node 1");
NodeB nodeB2 = new NodeB("Leaf node 2");
NodeA nodeA = new NodeA("Node with children", nodeB1, nodeB2);
NodeA emptyNodeA = new NodeA("Empty node");
Tree tree = new Tree("Tree", nodeA, emptyNodeA);
System.out.println(tree);
System.out.println(1 + getNodeCount(tree));
}
}
You could make N and V types implement specific interfaces so it will be possible to call some common operations on values and/or children.
EDIT: updated implementation with recursive method for node count retrieval
All you need is a Pair<A, B>. Example of trees:
Pair<A, Pair<B, C>>
Pair<Pair<A, B>, Pair<C, D>>
Pair<Pair<Pair<A, B>, Pair<C, D>>, Pair<Pair<E, F>, Pair<G, H>>
ps: don't do this. :)
This is an ideal spot for everything inheriting from "Node", but even that is unnecessary.\
What you probably want is a single generic "Node" object that contains references to your different classes (use composition before inheritance).
At that point, each of your different classes probably has something that can be done to them (otherwise why are they all in the same data structure?) Have them implement a common interface with this common functionality. The node class can delegate to this interface, or some other class can extract the class by this interface and act on it.
This would be better than trying to force something to also BE a node--do one simple thing and do it well.
--edit--
I can't really add an example that is relevant to you because you didn't post anything about your scenario.
But let's say that you have these different classes A, B * C. First of all are they related AT ALL aside from all being children of Object? Let's say they all implement interface "Iface". (If not, you can just replace Iface with "Object", but this really implies a bad design.)
Anyway, your "Node" object is just one object--
public class Node {
private List<node> children;
private Iface myObject;
... setters, getters, tree implementation, tree navigation, related garbage...
}
Now this is enough to create your tree. One thing that you might be able to do to make things smoother, have "Node implements Iface" and delegate any calls to it's object. For instance, if Iface contains an eat(Food foodtype) method, your node could implement Iface and have a method:
public void eat(Food foodtype) {
myObject.eat(foodtype);
}
This would make the "Node" class act as though it was the class it contained.
By the way--another relatively good idea at this point would be to make myObject "private final" and ensure it is not null in the constructor. That way you would always know it was set and none of your delegated members would have to do null checks.
I don't think generics are going to help you much in this case. Instead of having a different class for each level in the tree. What about one node class that has children and store a different class on each level. That should help eliminate a lot of the duplication.
I'm fairly new to Java, so this might have issues I'm not aware of, but it seems to work on a simple level at least.
Define your main Node class - this one will be the root of the tree.
public class NodeA {
private String _value;
private ArrayList<NodeA> _children;
private int _depth;
public NodeA (String value, int depth) {
_value = value;
_children = new ArrayList<NodeA>();
_depth = depth;
}
//probably want getters for _children and _value here
//this makes a new child, with its type depending on the depth of the tree it will
//be placed at. NodeB and NodeC will both inherit from NodeA
public void add(String value) {
switch (_depth) {
case 0:
_children.add(new NodeB(value, _depth+1));
break;
case 1:
_children.add(new NodeC(value, _depth+1));
break;
}
}
The add() method is going to create a new child for the node using the specified value. If you initialize the root of the tree as a NodeA with depth 0, you can add children to nodes and the tree should end up populated so that the next level contains all NodeB's, and the next all NodeC's. The code for NodeB and NodeC is super simple and could be replicated to create an arbitrary amount of Node levels (here is that code).
public class NodeB extends NodeA {
public NodeB(String value, int depth) {
super(value, depth);
}
//nothing else needed!
The code for NodeC is identical, except for the obvious replacements of B's with C's.
Hope this helps / is the kind of answer you wanted!