0
votes

I searched StackOverflow before posting this question but I wasn't able to find the right answer. Sorry if this is a repost. My problem is this:

I have a method that is overloaded in my java class:

class ABC{

    public boolean doSomething(String path, ArrayList<SomeObject> objList){
        // calling the method below in a loop
    }

    public boolean doSomething(String path, SomeObject obj){
       // Some code here
    }
}

I'm calling the above class from my groovy code like this:

void performDoSomething(ABC abc, String path, String[] strList){
    def list = []
    for (str in strList) {
        SomeObject sObj = new SomeObject(str)    // EDIT: sorry I missed this line before
        list.add(sObj)
    }
    if (abc) abc.doSomething(path, list)
}

The problem is that the groovy compiler is calling the abc.doSomething(String str, SomeObject obj) method instead of abc.doSomething(String str, ArrayList objList) method.

I'm using eclipse IDE with grails plugin (STS) and this is part of a bigger grails project (our company has a lot of legacy code in java).

Any ideas on how to fix this?
Thank you for your time!

EDIT: I have tried abc.doSomething(path, list as ArrayList) too but I'm getting the same result..

3
Is Groovy really supposed to turn a String[] into an ArrayList<Object>? - user207421
Sorry that was a typo by me, I have changed it now - vprasad
Is Groovy supposed to turn a [] into an ArrayList<Object>? - user207421
As you can see I'm using the string to create "SomeObject sObj = new SomeObject(str)" and adding sObj into the list. - vprasad
Your code works for me - the correct method get called, with no changes required. Now, I'm not using Eclipse, I just wrote up the two java classes in vim, and compiled at the command-line, then ran the groovy part as a script from the command-line - but it all seems to work fine. Oh, and btw, groovy does create an ArrayList for [] by default (it needs to be a concrete class to be instantiated, so List won't do...) - GreyBeardedGeek

3 Answers

2
votes

Can you reproduce this with a simple example using the classes you mention? I tried, but I got the expected behavior.

SomeObject.java::

public class SomeObject {
    public String what;
    public SomeObject(String what) {
        this.what = what;
    }
}

ABC.java:

import java.util.List;

public class ABC {
    public void doSomething(String path, List<SomeObject> objects) {
        System.out.println("Doing something with many objects");
        for (SomeObject obj : objects) {
            doSomething(path, obj);
        }
    }

    public void doSomething(String path, SomeObject obj) {
        System.out.println("Doing something with: " + obj.what);
    }
}

test.groovy:

void performDoSomething(ABC abc, String path, String[] strList){
    def list = []
    for (str in strList) {
        SomeObject sObj = new SomeObject(str)    // EDIT: sorry I missed this line before
        list.add(sObj)
    }
    if (abc) abc.doSomething(path, list)
}

performDoSomething(new ABC(), 'some path', ['hello', 'world'] as String[])

I run this doing (in the same directory as the files):

javac *.java
groovy test.groovy

And the output I get is:

Doing something with many objects
Doing something with: hello
Doing something with: world

Which means that the correct overloaded method, doSomething(String, List<SomeObject>), is being called by Groovy. This is what is expected, as Groovy uses the runtime type information on the methods to decide which overloaded version to call (an example of this can be found here). I would not recommend changing the signature of doSomthing as suggested, as it will pollute the class' interface unnecessarily; the problem is probably somewhere else.

1
votes

The simplest answer is to make sure your overloading isn't at all ambiguous.

Make the two calls have dramatically different APIs and see if the problem goes away or if the new error messages point you at a groovy issue.

public class ABC {
  public boolean doSomething(String path, int ignored, ArrayList<Object> objList){
    // calling the method below in a loop
  }

  public boolean doSomething(String path, Object obj){
   // Some code here
  }
}
1
votes

Okay I figured out the answer. It's an eclipse IDE problem, I had to run the "grails clean" command and the project was rebuilt. Now the groovy code is calling the correct java method.