generics编译并在Eclipse中运行,但不在javac中编译

注意 :这是从Comparable和Comparator合同中分离出来的null

此代码在Eclipse中编译并运行良好( 20090920-1017

 import java.util.*; public class SortNull { static <T extends Comparable<? super T>> Comparator<T> nullComparableComparator() { return new Comparator<T>() { @Override public int compare(T el1, T el2) { return el1 == null ? -1 : el2 == null ? +1 : el1.compareTo(el2); } }; } public static void main(String[] args) { List<Integer> numbers = new ArrayList<Integer>( Arrays.asList(3, 2, 1, null, null, 0) ); Comparator<Integer> numbersComp = nullComparableComparator(); Collections.sort(numbers, numbersComp); System.out.println(numbers); // "[null, null, 0, 1, 2, 3]" List<String> names = new ArrayList<String>( Arrays.asList("Bob", null, "Alice", "Carol") ); Comparator<String> namesComp = nullComparableComparator(); Collections.sort(names, namesComp); System.out.println(names); // "[null, Alice, Bob, Carol]" } } 

但它不能在javac 1.6.0_17javac 1.6.0_17 。 这是错误信息:

 SortNull.java:17: incompatible types; no instance(s) of type variable(s) T exist so that java.util.Comparator<T> conforms to java.util.Comparator<java.lang.Integer> found : <T>java.util.Comparator<T> required: java.util.Comparator<java.lang.Integer> Comparator<Integer> numbersComp = nullComparableComparator(); SortNull.java:25: incompatible types; no instance(s) of type variable(s) T exist so that java.util.Comparator<T> conforms to java.util.Comparator<java.lang.String> found : <T>java.util.Comparator<T> required: java.util.Comparator<java.lang.String> Comparator<String> namesComp = nullComparableComparator(); 2 errors 

有人可以解释为什么这种差异? 这是一个错误? 如果是这样,谁有错误?

这是一个确认的错误: 错误号6468354 。 以下是关联的摘录:

这个问题是由于有时javac的JLS3 15.12.2.8的实现忽略了recursion边界,有时候不是(在本例中)。 当recursion边界包含通配符时,在计算未提供的typesvariables时会包含这样的边界。 这使得后续的子typestest (Integer <: Comparable<? super T> ,其中T是推断的typesvariables)。

将在6369605之后被修复

在1.6.0_13的WinXP上也发生在我身上。 好吧,我会坚持使用Eclipse

你可以通过明确指定generics类来解决这个问题:

 Comparator<String> namesComp = Stack.<String>nullComparableComparator(); 

我有一个类似的问题,并从jdk1.6.0_16升级到jdk1.6.0_23,它没有任何代码更改就消失了。