为什么我在这里得到一个编译警告(Java中的var args方法调用)

dm7nw8vv  于 2023-05-05  发布在  Java
关注(0)|答案(6)|浏览(179)

来源:

public class TestVarArgs {
  public void varArgsMethod(Object ... arr) {
     System.out.println(arr.getClass().getName());
     for(Object o : arr) {
       System.out.println(o);
     }
  }

  public static void main(String[] args) {
    TestVarArgs tva = new TestVarArgs();
    tva.varArgsMethod(args);    
  }
}

编译:

javac TestVarArgs.java

错误:

TestVarArgs.java:15: warning: non-varargs call of varargs method with inexact argument type for last parameter;
cast to java.lang.Object for a varargs call
cast to java.lang.Object[] for a non-varargs call and to suppress this warning    
tva.varArgsMethod(args);     
^

1 warning

我使用的是javac 1.6.0_20,代码o/p表明无论如何都进行了非var arg调用。

ozxc1zmp

ozxc1zmp1#

这是因为String[]Object...不完全匹配。
你必须先将String[]转换为Object[](如果你想将字符串作为单独的参数传递)或Object(如果你只想要一个数组参数)。

tva.varArgsMethod((Object[])args);    // you probably want that

 tva.varArgsMethod( (Object) args);    // you probably don't want that, but who knows?

为什么这是一个警告而不是一个错误?向后兼容。在引入varargs之前,您让这些方法接受一个Object[],并且在该方法升级为使用varargs之后,针对该Object[]编译的代码仍然可以以相同的方式工作。JDK标准库中充满了这样的情况。例如,在Java5中,java.util.Arrays.asList(Object[])已更改为java.util.Arrays.asList(Object...),所有使用它的旧代码仍然可以编译和工作,无需修改。

isr3a4wc

isr3a4wc2#

String[]类型的参数应该显式转换为Object[],以便从TestVarArgs类型调用varargs方法varArgsMethod(Object...)。也可以强制转换为Object以进行varargs调用
如果将String[]转换为Object[](ref:tva.varArgsMethod((Object[])args);

将方法的参数更改为String[]
(ref:public void varArgsMethod(String ... paramArr)

prdp8dxp

prdp8dxp3#

将方法修改为

public void varArgsMethod(String ... arr)
tuwxkamq

tuwxkamq4#

对Object和Object[]的强制转换对我来说不起作用,它破坏了我的代码,导致“遇到数组值参数绑定,但期望[java.lang.String(n/a)]”和其他随机性。
下面是显示警告(subj)的代码行,其中filter.getStates()的类型为String[]
p.add(root.join(DeviceEntity_.state,JoinType.LEFT).get(ClassifierEntity_.CODE).in(filter.getStates()));
有效的解决方案是使用Arrays.asList(filter.getStates())而不是强制转换。祝你好运!

ntjbwcob

ntjbwcob5#

警告信息的措辞确实非常令人困惑,所以最好尝试一个例子。我用jshell测试了两种可能性(强制转换为Object vs Object[]):

void printVarArgs(String msg, Object obj, Object... args) {
  System.out.printf("%s, %s, %s%n", msg, obj, java.util.Arrays.deepToString(args));
}

下面是3种调用的结果:
1.无铸件:

jshell> printVarArgs("Foo", 1, new String[] {"a", "b"})
Foo, 1, [a, b]
|  Warning:
|  non-varargs call of varargs method with inexact argument type for last parameter;
|    cast to java.lang.Object for a varargs call
|    cast to java.lang.Object[] for a non-varargs call and to suppress this warning
|  printVarArgs("Foo", 1, new String[] {"a", "b"})
|                         ^---------------------^

1.转换为Object

jshell> printVarArgs("Foo", 1, (Object)(new String[] {"a", "b"}))
Foo, 1, [[a, b]]

1.转换为Object[]

jshell> printVarArgs("Foo", 1, (Object[])(new String[] {"a", "b"}))
Foo, 1, [a, b]
总结:

如果在调用该方法时将String[]值的参数转换为Object,则该方法将看到单个“var-arg”(即Object... args参数变成一个数组,其中包含一个嵌套的String[]作为其唯一的元素),在我们的示例中,将其打印为[[a, b]]
如果将其强制转换为Object[],则该方法将获得2个“var-args”("a""b"),并将args参数打印为[a, b]。这与没有显式强制转换的原始调用完全相同。强制转换为Object[]的唯一好处是抑制了编译器警告。

dxpyg8gm

dxpyg8gm6#

一个优雅的方法来摆脱这个警告:而不是tva.varArgsMethod(args)调用tva.varArgsMethod(Arrays.stream(args).toArray())显式显示您传递多个参数。另一种摆脱警告的方法是使用以下调用:

tva.varArgsMethod(Arrays.asList(args).toArray())

无论如何,我们必须将args转换为Array。

相关问题