我有一个类,有两个这样的方法:
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);
}
}
我希望编译器会给出错误,因为方法调用不明确。相反,会调用第二种方法。
在我们的例子中,不明确的方法是从数据库方法和稍后添加的可变参数生成的。现在我们不知道如何避免像示例中那样的方法调用问题。
其他人有这个问题并知道如何解决吗?
我按照这个给出答案:
问题是如何找到这样的方法调用,其中第一个 应该调用方法(并且是在我们更改代码之前 生成器),但第二个被调用。
首先,正如已经指出的那样,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 似乎是一种方法 --- 获取应用程序中的所有包并检查它们。
此时您将有两个列表:
不明确的可变参数方法用法列表
不明确的可变参数方法列表。
通过交叉这两者,您可以找出可能会出现问题的地方。
接下来,我建议检查添加第二个方法之前的代码版本,并找到第一个方法的所有用法。显然必须消除这些歧义,以支持 HEAD 版本中的第一种方法。我想,这样一来,剩下的呼叫数量就会相当有限。
doIt("someString", null, null)
,让方法调用更具体。话虽这么说,真正的答案是重写方法以将 Collection 作为参数。使用可变参数往往会导致比它解决的问题更多的问题。
包装示例:
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);
}
}