Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7031404

Reference is ambiguous with generics

    XMLWordPrintable

Details

    • x86
    • windows_7

    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 :
      Microsoft Windows [Version 6.1.7600]

      A DESCRIPTION OF THE PROBLEM :
      I'm having quite a tricky case here with generics and method overloading. Check out this example class:

      public class Test {
          public <T> void setValue(Parameter<T> parameter, T value) {
          }

          public <T> void setValue(Parameter<T> parameter, Field<T> value) {
          }

          public void test() {
              // This works perfectly. <T> is bound to String
              // ambiguity between setValue(.., String) and setValue(.., Field)
              // is impossible as String and Field are incompatible
              Parameter<String> p1 = getP1();
              Field<String> f1 = getF1();
              setValue(p1, f1);

              // This causes issues. <T> is bound to Object
              // ambiguity between setValue(.., Object) and setValue(.., Field)
              // is possible as Object and Field are compatible
              Parameter<Object> p2 = getP2();
              Field<Object> f2 = getF2();
              setValue(p2, f2);
          }

          private Parameter<String> getP1() {...}
          private Parameter<Object> getP2() {...}

          private Field<String> getF1() {...}
          private Field<Object> getF2() {...}
      }

      The above example compiles perfectly in Eclipse (Java 1.6), but not with the Ant javac command (or with the JDK's javac command), where I get this sort of error message on the second invocation of setValue:

          reference to setValue is ambiguous, both method setValue(org.jooq.Parameter,T) in Test and method setValue(org.jooq.Parameter,org.jooq.Field) in Test match

      According to the specification and to my understanding of how the Java compiler works, the most specific method should always be chosen: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#20448

      In any case, even if <T> is bound to Object, which makes both setValue methods acceptable candidates for invocation, the one with the Field parameter always seems to be more specific. And it works in Eclipse, just not with the JDK's compiler.

      Note: I discussed this issue on stackoverflow as well. I'm not entirely sure who's right:
      http://stackoverflow.com/questions/5361513/reference-is-ambiguous-with-generics

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See description

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected result: Compile class from description in Eclipse, works
      ACTUAL -
      Actual result: Compile class from description with javac, doesn't work

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      reference to setValue is ambiguous, both method setValue(org.jooq.Parameter,T) in Test and method setValue(org.jooq.Parameter,org.jooq.Field) in Test match

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Test {
          public <T> void setValue(Parameter<T> parameter, T value) {
          }

          public <T> void setValue(Parameter<T> parameter, Field<T> value) {
          }

          public void test() {
              // This works perfectly. <T> is bound to String
              // ambiguity between setValue(.., String) and setValue(.., Field)
              // is impossible as String and Field are incompatible
              Parameter<String> p1 = getP1();
              Field<String> f1 = getF1();
              setValue(p1, f1);

              // This causes issues. <T> is bound to Object
              // ambiguity between setValue(.., Object) and setValue(.., Field)
              // is possible as Object and Field are compatible
              Parameter<Object> p2 = getP2();
              Field<Object> f2 = getF2();
              setValue(p2, f2);
          }

          private Parameter<String> getP1() {...}
          private Parameter<Object> getP2() {...}

          private Field<String> getF1() {...}
          private Field<Object> getF2() {...}
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Avoid method overloading in this case

      Attachments

        Activity

          People

            dlsmith Dan Smith
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: