Generics compiles and runs in Eclipse, but doesn&#

2020-01-23 13:09发布

Note: This is a spin-off from Comparable and Comparator contract with regards to null

This code compiles and runs fine in 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]"
   }
}

And yet it doesn't compile on javac 1.6.0_17. This is the error message:

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

Can someone explain why the discrepancy? Is this a bug? If so, who has the bug?

3条回答
够拽才男人
2楼-- · 2020-01-23 13:18

You can get around this by explicitly specifying the generic class:

Comparator<String> namesComp = Stack.<String>nullComparableComparator();
查看更多
欢心
3楼-- · 2020-01-23 13:20

This is a confirmed bug: Bug ID 6468354. Here's an extract of relevance:

This problem is caused by the fact that sometimes javac's implementation of JLS3 15.12.2.8 ignores recursive bounds, sometimes not (as in this case). When recursive bounds contains wildcards, such bounds are included when computing uninferred type variables. This makes subsequent subtyping test (Integer <: Comparable<? super T> where T is a type-variable to be inferred).

Will be fixed after 6369605

Occured to me on WinXP with 1.6.0_13 as well. Ah well, I'll just stick using Eclipse :)

查看更多
Bombasti
4楼-- · 2020-01-23 13:40

I had a similar problem and upgraded from jdk1.6.0_16 to jdk1.6.0_23 and it went away without any code changes.

查看更多
登录 后发表回答