Java Generics, Cannot Convert from E to E - java

My code cannot convert from E to E. I can do a cast to type E but it seems redundant at this stage. My array is already declared as E-type.
import java.util.Iterator;
public class DataTypeDemo<E>
{
private E[] data = (E[]) new Object [10];
public MyIterator newIterator()
{
return new MyIterator();
}
private class MyIterator<E> implements Iterator<E>
{
private int location;
public boolean hasNext()
{
return location < data.length;
}
public E next()
{
return (data[location++]); // error here
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
}
Compiler, throws this error:
DataTypeDemo.java:23: incompatible types
found : E
required: E

Your inner type introduces it's own type variable:
private class MyIterator<E /* this is the problem*/> implements Iterator<E>
And thereby overwrites the outer class type variable
Change your type declaration to this:
private class MyIterator implements Iterator<E>
Reference:
Generics FAQ (although this problem is not mentioned literally, it is implied by this FAQ entry)

The root of your problem is that an inner class of yours.
For the compiler, there are no guarantees that the two E's are of the same type.
import java.util.Iterator;
import java.util.ArrayList;
public class DataTypeDemo<E>
{
private ArrayList<E> data = new ArrayList<E>(10);
private class MyIterator implements Iterator<E>
{
private int location;
public boolean hasNext()
{
return location < data.size();
}
public E next()
{
return data.get(location++);
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
}
Though once you are aware of the problem, feel free to implement your own solution ;)
Happy hacking.

That's because you've given the inner class MyIterator its own type parameter E. Note that that E is a different type parameter than the E of the enclosing class (you've named them both E, but they are two different type parameters).
Just leave off the type parameter for the inner class:
private class MyIterator implements Iterator<E> {

I think that the problem is that your nested iterator type is defined as a generic class also parameterized over an unrelated type named E. To fix this, change
private class MyIterator<E> implements Iterator<E>
To
private class MyIterator implements Iterator<E>
This first declaration says that the iterator for your type can be parameterized over any type, not just the type of the outer container. It also introduces a new type variable called E that is separate from the E in the outer declaration. This second definition says that the for any container type, there is one iterator type that isn't generic with respect to the outer type. This is probably what you intended.

Related

In Java, why using generic on an inner class doesn't work? [duplicate]

This question already has answers here:
How do I get an inner class to inherit enclosing class' generic type?
(5 answers)
Closed 6 years ago.
My compiler is JDK 6.0_65, and following are my codes (Deque.java):
import java.util.Iterator;
public class Deque<Item> implements Iterable<Item> {
private Node first;
private Node last;
private class Node {
Item value;
Node next;
}
public Deque(){} // construct an empty deque
public Iterator<Item> iterator() {
// return an iterator over items in order from front to end
return new DequeIterator<Item>();
}
private class DequeIterator<Item> implements Iterator<Item> {
private Node current = first;
public boolean hasNext() {
return current.next != null;
}
public Item next() {
Item item = current.value;
current = current.next;
return item;
}
public void remove() {}
}
public static void main(String[] args) {
// unit testing
Deque<Integer> dq = new Deque<Integer>();
}
}
In the outer scope :
public class Deque<Item> implements Iterable<Item> {
is used.
And in the inner scope:
private class DequeIterator<Item> implements Iterator<Item> {
is used.
In the scope of DequeIterator. I expected the local-scope (inner-class-scope) Item will shadow the class-scope Item from Deque<Item>.
However, during compiling stage, javac will throw an error like this:
Deque.java:2: error: incompatible types
Item item = current.value;
^
required: Item#2
found: Item#1
where Item#1,Item#2 are type-variables:
Item#1 extends Object declared in class Deque
Item#2 extends Object declared in class Deque.DequeIterator
It says Item#2 and Item#1 is incompatible types, which looks quite confusing to me because I have passed the type parameter Item into DequeIterator using new DequeIterator<Item>().
Does anyone have any idea about this?
I expected the local-scope (inner-class-scope) Item will shadow the class-scope Item from Deque<Item>
This is basically precisely what happened - the inner-scope Item shadowed the outer one. It does not matter that you've passed the outer Item to the constructor. The inner class has problems compiling because you're trying to assign a value of type outer-Item to a variable of type inner-Item.
To fix this just make the nested class non-generic:
private class DequeIterator implements Iterator<Item>
In that way you will use the outer-Item without declaring another Item type parameter which you don't really need.
Yes inner class generic Item shadows generic enclosing class Item, this is exactly why the compiler complains. You wrote Item item=current.value (and that is the problem). Here Item refers to the generic type of the inner class, but current.value is of generic type Item of the enclosing class. These types are different! The compiler named them Item#1 and Item#2. You just have to remove the genericity from inner class DequeIterator:
public class Deque<Item> implements Iterable<Item> {
private static class DequeIterator implements Iterator<Item> {
}
}
There's no guarantee that Item#1 and Item#2 will always be the same. You could add a method like this to Deque:
public Iterator<Integer> boom() {
return new DequeIterator<Integer>();
}
This obviously doesn't make any sense, but since the Items of the iterator class aren't related to the enclosing class' Items (because the inner Item type parameter shadows the outer) it's perfectly legal.
There's no reason for you to give the DequeIterator class a type parameter though, you can simply declare it thus:
private class DequeIterator implements Iterator<Item> {
// Content remains unchanged
}
Try this, and you may even remove the <T>:
private class DequeIterator<T> implements Iterator<Item> {
...
}
I think the problem is some sort of shadowing problem where the inner and outer Item are considered different.

weird typing error with private iterator in generic class

I'm implementing a linked list in Java 1.7 and I don't understand this behaviour. The parts of the code that matter are this:
public class LListSent<T> implements Iterable<T>{
//...
public T get(int pos) {
//...
}
//...
private class LListSentIterator {
private final LListSent list;
private int currPos;
private LListSentIterator(LListSent list) {
this.list = list;
currPos = 0;
}
//...
#Override
public T next() {
return list.get(currPos++); //exception in this line
}
}
}
The exception I get is:
incompatible Type: Object cannot be converted to T
where T is a type-variable:
T extends Object declared in class LListSent
eve though left.get return a T object. Why does this happen?
Your list variable is of type LListSent which is the raw type (so not parametrized) as such the get method called on this instance will return Object and not T.
Change the type of your variable to LListSent<T>.
Note that this will work because LListSentIterator is an inner class and has access to the type variable T.
A cleaner solution would be to parametrized your LListSentIterator class with a type parameter S and so your list variable would become of type : LListSent<S>

Bound Mismatch on new object of generic class

I have an error occuring with a program for an assignment. In it, I have to create an own generic
public class LinkedList<E extends Comparable<T>> implements List<E> {
the implemented Interface is:
public interface List<E extends Comparable<T>> { }
Now, whenever I try to create a new object of the type LinkedList as follows:
LinkedList<Termin> k = new LinkedList<Termin>();
eclipse gives me the following error:
Bound mismatch: The type Termin is not a valid substitute for the bounded parameter > of the type
LinkedList
the class declaration of the class Termin is as follows:
public class Termin implements Comparable<T> { }
in case you need the constructor and variables of the LinkedList object:
private E item;
private LinkedList<E> next;
//Constructor
public LinkedList() {
item = null;
next = null;
}
With a little google magic, I also found out that there once was a bug involving generics in eclipse that gave the same error for no reason.
I suppose some of my declarations aren't entirely correct.
The way the code is written, it cannot compile for a number of reasons, including the lack of specification of the T type, which is not explicitly declared.
One solution is to remove T and replace it with a known Java type (e.g., Object).
A more generic solution is to include T, which means two generic types have to be used.
For the latter case, the code could be something like:
// LinkedList class
public class LinkedList<T, E extends Comparable<T>> implements List<T, E> {
private E item;
private LinkedList<T, E> next;
// Constructor
public LinkedList() {
item = null;
next = null;
}
public static void main(String[] args) {
// Example statement, where T = Long.class and E = String.class
LinkedList<Long, Termin<String>> k = new LinkedList<Long, Termin<String>>();
}
}
and
// List interface
public interface List<T, E extends Comparable<T>> { }
and
// Termin class
public class Termin<T> implements Comparable<T> {
#Override
public int compareTo(T o) {
return 0; // Actual comparison needs to be implemented
}
}

Implementation of Iterable in Java

//project.java
import MULTISET;
public class Bag<E extends Keyed> implements Iterable<E> {
//cannot find symbol. symbol: class Iterator. location: class project.Bag<E>
public Iterator<E> iterator() {
return new ArrIterator(this);
}
//same error as above
public class ArrIterator implements Iterator<E> {
Bag<E> arr;
int coun;
public ArrIterator(Bag<E> arr) {
this.arr = arr;
this.coun = 0;
}
public boolean hasNext() {
return this.coun < arr.cardinality();
}
public E next() {
if (!hasNext()) {
throw new NoItemException();
}
return arr.getArray()[coun+1];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
//MULTISET.java
//cannot find symbol. symbol: class Iterator. location: interface MultiSet<E>
public interface MultiSet<E extends Keyed> extends Iterable<E> {
public Iterator<E> iterator();
}
I'm trying to do foreach loops on type Bag, and I get the two commented errors. I'm not too familiar with ADT, generics, or iterators, but I thought I did the correct thing.
What is missing and/or wrong here? This isn't my complete code, but everything else I've left out works. There's a problem somewhere in the above code snippet. An example I was following is more or less 1:1 with my own code, but mine doesn't seem to work.
The problem is that your inner class ArrIterator is re-defining another generic type parameter <E> when it's still in scope from your outer class, Bag. This causes the new E not to match the old E.
According to Section 6.3 of the JLS:
The scope of a class's type parameter (ยง8.1.2) is the type parameter section of the class declaration, the type parameter section of any superclass or superinterface of the class declaration, and the class body.
Remove the re-declaration of E in your inner class ArrIterator and let its extends clause use the E already in scope.
public class ArrIterator implements Iterator<E> {
Then your iterator() method doesn't have to return a generic ArrIterator.
public Iterator<E> iterator() {
return new ArrIterator(this);
}
Also, your hasNext method in your iterator should return boolean to match the Iterator interface.

Generic class implementing Iterable

I want to have a generic class that implements Iterable (let's call it ImplIterable) of type T that implements an Iterable interface over some class (that isn't of the generic class type); for example:
public class ImplIterable <T> implements Iterable<A> {
private A[] tab;
public Iterator<A> iterator() {
return new ImplIterator();
}
// doesn't work - but compiles correctly.
private class ImplIterator implements Iterator<A> {
public boolean hasNext() { return true; }
public A next() { return null; }
public void remove() {}
}
}
Where A is some class. Now, this code won't compile:
ImplIterable iable = new ImplIterable();
for (A a : iable) {
a.aStuff();
}
But this will:
Iterable<A> = new ImplIterable();
for (A a : iable) {
a.aStuff();
}
I don't understand why the latter doesn't compile and why can't I iterate over ImplIterable if it properly implements iterable. Am I doing something wrong/is there some workaround for this type of problems?
When you use a generic class without a generic parameter, all generics in that class are disabled.
Since ImplIterable is generic, and you're using it as a non-generic class, the generic parameters inside of it vanish, and it becomes an Iterable (non-generic) of Objects.

Categories

Resources