Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-9245

synthetic constructors should be ignored

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • None
    • 3.0.0-rc-2
    • None
    • None

    Description

      Groovy should ignore synthetic constructors when instantiating objects, or at most fall back to them if no non-synthetic one is found.

      If you have a Java class with a private constructor and inner classes (doesn't matter whether static or non-static) that are subclasses of the outer class and call one of the private super-constructors (for example by not calling super explicitly and having a parameterless private constructor in the super class, or by calling any private constructor explicitly using super), an additional synthetic package-private constructor with a synthetic anonymous inner class of the outer class as additional argument that then forwards the call to the private constructor is created by the compiler so that the inner class has something non-private to call as super constructor.

      So assuming you have this Java class:

      class Foo {
          private Foo() {
          }
      
          public Foo(String foo) {
          }
      
          private static class Bar extends Foo {
          }
      }
      

      and then from Groovy try to call `new Foo(null)` you get the quite unexpected (unless you are aware of compiler internals)

      Ambiguous method overloading for method net.kautler.command.api.restriction.Foo#<init>.
      Cannot resolve which method to invoke for [null] due to overlapping prototypes between:
      	[class net.kautler.command.api.restriction.Foo$1]
      	[class java.lang.String]
      

      Or with this:

      class Foo {
          private Foo() {
          }
      
          private Foo(String foo) {
          }
      
          public Foo(String foo, String bar) {
          }
      
          private static class Bar extends Foo {
              public Bar() {
                  super(null);
              }
          }
      }
      

      and you try to do from Groovy `new Foo(null, null)`, you get

      Ambiguous method overloading for method net.kautler.command.api.restriction.Foo#<init>.
      Cannot resolve which method to invoke for [null, null] due to overlapping prototypes between:
      	[class java.lang.String, class net.kautler.command.api.restriction.Foo$1]
      	[class java.lang.String, class java.lang.String]
      

      I'd suggest when searching for a constructor to invoke to first filter out the synthetic constructors (or at least the synthetic constructors with a synthetic anonymous inner class as last paramter) and only if none was found, search in the synthetic ones.

      Attachments

        Issue Links

          Activity

            People

              emilles Eric Milles
              vampire Björn Kautler
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 0.5h
                  0.5h