Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - local class and generics, why compiler warning?

Named local classes are very rarely used, usually local classes are anonymous. Does anybody know why the code below generates a compiler warning?

public class Stuff<E> {
  Iterator<E> foo() {
    class InIterator implements Iterator<E> {
      @Override public boolean hasNext() { return false; }
      @Override public E next() { return null; }
      @Override public void remove() { }
    }
    return new InIterator();
  }
}

The warning is in new InIterator() and it says

[unchecked] unchecked conversion
found   : InIterator
required: java.util.Iterator<E>

If the class, unchanged, is made anonymous, or if it is made a member, the warning goes away. However, as a named local class, it requires a declaration class InIterator<E> implements ... for the warning to go away.

What's going on?

like image 985
Yardena Avatar asked Apr 21 '09 14:04

Yardena


1 Answers

I believe what's happening is you are ignoring the generic type argument by naming InIterator without a reference to the generic in the signature (even though it is present in the interface).

This falls into the category of silly compiler warnings: you've written the class so that 100% InIterator instances will implement Iterator<E>, but the compiler doesn't recognize it. (I suppose this depends on the compiler. I don't see the warning in my Eclipse compiler, but I know that the Eclipse compiler handles generics slightly differently than the JDK compiler.)

I argue that this is less clear, and less close to what you mean, but perhaps more compiler friendly, and ultimately equivalent:

public class Stuff<E> {
  Iterator<E> foo() {
    class InIterator<F> implements Iterator<F> {
      @Override public boolean hasNext() { return false; }
      @Override public E next() { return null; }
      @Override public void remove() { }
    }
    return new InIterator<E>();
  }
}
like image 53
David Berger Avatar answered Oct 27 '22 13:10

David Berger