Java Bug使用varargs的模糊方法?

时间:2014-02-07 17:08:50

标签: java compiler-construction variadic-functions ambiguous

我有一个类有两个这样的方法:

public class Dummy{
  public void doIt(String arg1, File arg2, Writer... ctx){
    // Do something very important...
  }

  public void doIt(String arg1, Writer... ctx){
    // Do something else...
  }

  public static void main(String[] args){
    new Dummy().doIt("Test", null);
  }
}

我希望,编译器会给出错误,因为方法调用是不明确的。而是调用第二种方法。

在我们的例子中,ambigous方法是从数据库方法和稍后添加的varargs生成的。现在我们不知道如何避免方法调用的问题,如示例中所示。

是否有其他人有这个问题,并想知道如何解决它?

3 个答案:

答案 0 :(得分:2)

我根据这个给出答案:

  

问题是如何找到这样的方法调用,第一个   应该调用方法(并且在我们更改代码之前)   生成器),但第二个被调用。

首先,正如已经指出的那样,Java编译器会发出有关此类方法用法的警告。它看起来像这样:

  

com / stack / undsprlbl / varargs / Main.java:10:警告:非varargs调用   最后一个参数的不精确参数类型的varargs方法;

可以轻松grep - 来自javac输出。

其次,你可以考虑在这些方面为你的代码编写一些自测:

    Class cl = Ambiguity.class;
    Method[] methods = cl.getDeclaredMethods();
    Set<String> varargsMethods = new HashSet<String>();
    for (Method method : methods) {
        Class c[] = method.getParameterTypes();
        if(c.length > 0)
        {
            Class last = c[c.length - 1];
            if(last.isArray())
            {
                if(varargsMethods.contains(method.getName()))
                    System.out.println("Method " + cl.getName() + "#"+ method.getName() + " looks suspicious.");
                else
                    varargsMethods.add(method.getName());
            }
        }
    }

理解你应该迭代所有的课程,而不是直接提及。这个answer似乎是一种方法 - 在应用程序中获取所有包并检查它们。

此时您将有两个列表:

  1. 模棱两可的varargs方法用法列表

  2. 模棱两可的varargs方法列表。

  3. 通过跨越这两个,你可以找出你可能会遇到问题的地方。

    接下来,我建议在添加第二种方法之前检查代码的版本,并查找第一种方法的所有用法。那些显然必须消除歧义,支持HEAD版本中的第一种方法。这样,我想,剩下这些电话的数量将非常有限。

答案 1 :(得分:0)

您的具体问题的答案是执行其他人所说的内容,并致电doIt("someString", null, null)以使方法调用更具体。

话虽这么说,但真正的答案是重写方法以将Collection作为参数。使用varargs往往会导致比解决更多的问题。

答案 2 :(得分:0)

我建议创建一个明确的包装类,以防止意外滥用生成的类。

示例包装器:

public class NicerDummy{
    Dummy dummy;
    public NicerDummy(){
        dummy = new Dummy(); 
    }

    public void doSomething(String arg1, Writer... ctx){
        dummy.doIt(arg1, Writer);
    }

    public void doSomethingElse(String arg1, File arg2, Writer... ctx){
        dummy.doIt(arg1, arg2, ctx);
    }
}