JDK-7028331 : Statement with generics fails to compile in one line, compiles in two lines
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u24
  • Priority: P4
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: linux
  • CPU: x86
  • Submitted: 2011-03-16
  • Updated: 2012-09-06
  • Resolved: 2011-03-17
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux work-laptop 2.6.35-27-generic #48-Ubuntu SMP Tue Feb 22 20:25:46 UTC 2011 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The compiler seems to get confused when dealing with lower bounded wildcards in generics. The code example given demonstrates the problem. The error message indicates that the compiler thinks the type should be one thing, when it seems plain that it should be another, and in fact "reminding" the compiler of the correct type via a variable declaration seems to make it happy.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the given source code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Success
ACTUAL -
Failure--see error message

ERROR MESSAGES/STACK TRACES THAT OCCUR :
<T>contains(java.util.List<T>,T) in com.foo.Foo cannot be applied to (java.util.List<java.util.Comparator<? super java.lang.Object>>,com.foo.Foo.SomeComparator<java.lang.String>)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package com.foo;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class Foo {
    public static void main(String[] args) {
        List<Comparator<? super String>> list = buildList(new SomeComparator<String>("bar"));
        boolean b = contains(
                list,
                new SomeComparator<String>("x"));
        System.out.println(b);
    }

    public static <T> boolean contains(List<T> objects, T object) {
        return objects.contains(object);
    }

    public static <T> List<Comparator<? super T>> buildList(Comparator<? super T>... comparator) {
        return Arrays.asList(comparator);
    }

    private static class SomeComparator<T> implements Comparator<T> {
        public SomeComparator(T arg) {}
        public int compare(T o1, T o2) { return 0; }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
"Help" the compiler recognize the correct type by splitting the problem line (first line of the main method) into two lines, like so:
        List<Comparator<? super String>> list = buildList(new SomeComparator<String>("bar"));
        boolean b = contains(
                list,
                new SomeComparator<String>("x"));

Comments
EVALUATION The given source code compiles OK under JDK 6 and JDK 7. $ /opt/jdk/1.6.0/bin/javac play/Foo.java Note: play/Foo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. $ /opt/jdk/1.7.0/bin/javac play/Foo.java Note: play/Foo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. $
17-03-2011