【问题标题】:Groovy compiler calling wrong overloaded java methodGroovy 编译器调用错误的重载 java 方法
【发布时间】:2012-03-20 23:54:19
【问题描述】:

我在发布此问题之前搜索了 StackOverflow,但找不到正确答案。抱歉,如果这是转发。我的问题是这样的:

我的 java 类中有一个方法被重载:

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
    }
}

我从我的 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)
}

问题在于 groovy 编译器正在调用 abc.doSomething(String str, SomeObject obj) 方法而不是 abc.doSomething(String str, ArrayList objList) 方法。

我正在使用带有 grails 插件 (STS) 的 eclipse IDE,这是一个更大的 grails 项目的一部分(我们公司在 java 中有很多遗留代码)。

关于如何解决此问题的任何想法?
感谢您的宝贵时间!

编辑:我试过了 abc.doSomething(路径,列表为 ArrayList) 也是,但我得到了相同的结果..

【问题讨论】:

  • Groovy 真的应该把 String[] 变成 ArrayList&lt;Object&gt; 吗?
  • 对不起,我打错了,我现在改了
  • Groovy 是否应该将 [] 转换为 ArrayList
  • 如您所见,我正在使用字符串创建“SomeObject sObj = new SomeObject(str)”并将 sObj 添加到列表中。
  • 您的代码适用于我 - 调用正确的方法,无需更改。现在,我没有使用 Eclipse,我只是在 vim 中编写了两个 java 类,并在命令行中编译,然后从命令行将 groovy 部分作为脚本运行——但这一切似乎都很好。哦,顺便说一句,groovy 确实默认为 [] 创建一个 ArrayList(它需要是一个要实例化的具体类,所以 List 不会这样做......)

标签: java grails groovy


【解决方案1】:

你能用你提到的类通过一个简单的例子重现这个吗?我试过了,但我得到了预期的行为。

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[])

我这样做(在与文件相同的目录中):

javac *.java
groovy test.groovy

我得到的输出是:

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

这意味着 Groovy 正在调用正确的重载方法 doSomething(String, List&lt;SomeObject&gt;)。这是预期的,因为 Groovy 使用方法上的运行时类型信息来决定调用哪个重载版本(可以在 here 找到一个示例)。我建议更改doSomthing as suggested 的签名,因为它会不必要地污染类的接口;问题可能出在其他地方。

【讨论】:

  • 感谢您的回复,但问题出在 eclipse grails/groovy 插件上,而不是我的代码 :)
【解决方案2】:

最简单的答案是确保您的重载完全没有歧义。

让这两个调用具有截然不同的 API,看看问题是否会消失,或者新的错误消息是否将您指向一个常规问题。

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
  }
}

【讨论】:

  • 我可以这样做,但是我们的(旧)代码库中的许多其他 java 类都使用了 java 类“ABC”。我们正在将我们的框架升级到 grails,如果我采用这种方法,还有更多的重载方法需要更改。
  • 另外,我刚刚尝试了您的方法,它似乎调用了正确的方法。但我认为我们负担不起在整个代码库中使用此解决方案:/
  • 对不起,我不清楚。我希望消除通话歧义会突出真正的问题。
【解决方案3】:

好的,我想出了答案。这是一个 Eclipse IDE 问题,我必须运行“grails clean”命令并重建项目。现在 groovy 代码正在调用正确的 java 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2016-04-13
    相关资源
    最近更新 更多