Java - 本地类和泛型,为什么编译器警告?

问题描述:

命名为local classes很少使用,通常本地类是匿名的。有谁知道为什么下面的代码会生成编译器警告?Java - 本地类和泛型,为什么编译器警告?

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(); 
    } 
} 

警告是new InIterator()和它说

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

如果类,不变的,是由匿名,或者如果它是由一个成员,警告消失。但是,作为已命名的本地班级,它需要声明class InIterator<E> implements ...以使警告消失。

发生了什么事?

+0

只是出于好奇,我的编译器不会抱怨这个警告......您使用的是什么JVM? – 2009-04-21 14:57:06

+0

Sun Java 6更新12 – Yardena 2009-04-21 15:54:49

我现在确信这是一个javac错误。上面给InIterator添加一个通用参数的方法隐藏或替换E是没有用的,因为它们排除了迭代器做一些有用的事情,比如返回一个类型为E的东西的东西的E的元素。

然而,这编译与没有警告(感谢Jorn的提示):

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

绝对是一个错误。

我相信发生了什么是你忽略了泛型类型参数,命名InIterator而没有引用签名中的泛型(即使它存在于接口中)。

这属于愚蠢的编译器警告类别:您已编写该类,以便100%的实例将实现Iterator<E>,但编译器无法识别它。 (我想这取决于编译器,我没有看到我的Eclipse编译器中的警告,但我知道Eclipse编译器处理的泛型与JDK编译器略有不同)。我认为这不太清楚,少接近你的意思,但也许更友好的编译器,并最终相当于:

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>(); 
    } 
} 
+0

谢谢大卫。 IntelliJ IDEA也没有显示任何警告,只是Sun javac。我知道如何解决这个问题,我只是想知道这种编译器行为是否存在一些奇怪而合法的原因,或者它是一个错误。 – Yardena 2009-04-21 15:01:36

+0

啊,IDE和javac编译器之间的差异......这怎么讨厌:( – Jorn 2009-04-21 15:24:06

嗯,这里没有任何警告。

import java.util.Iterator; 

public class Stuff<E> { 
    Iterator<E> foo() { 
     class InIterator implements Iterator<E> { 
      public boolean hasNext() { 
       return false; 
      } 

      public E next() { 
       return null; 
      } 

      public void remove() { 
      } 
     } 
     return new InIterator(); 
    } 

    public static void main(String[] args) { 
     Iterator<String> i = new Stuff<String>().foo(); 
    } 
} 

是的,我也同意这应该是一个错误。如果你将本地类从方法中“提升”到成员类中,它也可以正常工作。除了不同的范围和局部变量之外,两者之间没有太大的区别。

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