繁体   English   中英

构造函数模糊与java 8中的varargs

[英]Constructor ambiguity with varargs in java 8

在下面的类中,由于对this()的模糊调用,我得到了Java 8的编译错误。 但是,使用Java 6,这个类编译得很好。 我知道我可以使用工厂方法重构这个但是对于发生问题的实际类,我强烈希望现在维护当前的API。

有没有人能想到一种方法来解决歧义而不改变外部API?

public class Vararg8 {

    public Vararg8(final Object... os) {}

    public Vararg8(final boolean b,
                   final String s,
                   final int... is) {}

    public Vararg8() {
        this(true, "test", 4, 5, 6);
    }
}

你可以通过传递一个显式的int[]数组来做到这一点:

public Vararg8()
{
  this(true, "test", new int[]{4, 5, 6});
}

您可能会注意到,从某种意义上说,这仍然是模棱两可的:您传递的内容仍然与Object...构造函数兼容。 这样做的原因是方法分辨率处于不同阶段,只有最后阶段允许考虑varargs参数。 因为你已经使用了一个显式数组,所以它可以很好地击中第二个数组,而不需要扩展varargs。 没有varargs扩展就无法击中第一个,所以直到最后阶段都不会考虑。

请参阅相应的JLS文档

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍然排除使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第三阶段。

第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合。

试试这个:

public Vararg8()
{
  this(true, "test", new int[]{4, 5, 6});
}

使用显式int数组应该可以解决您的问题。

  public Vararg8() {
        this(true, "test",new int[]{ 4, 5, 6});
    }

您可以使用generic在运行时推断类型,但这会将它们转换为Boxed形式。 这当然是性能神风,如果你在那里做了很多算术或必须打包很多原语,但会让所有现有的代码正常工作。

如果您已经使用了对象类型,那么此解决方案将不会为您带来任何成本。

看起来像这样:

public<A extends Boolean, B extends String, C extends Integer> Disambiguate(final A booleanPar,
                                        final B stringPar,
                                        final C... integerPar) {System.out.println("Im in the specific one");}

public<T extends Object> Disambiguate(final T... os) {System.out.println("Im in the general one");}

public static void main(String[] args) {
    new Disambiguate(true, "test", 4, 5, 6);
}

您可以将泛型用于1.5及更高版本的“向后兼容性”,并使所有现有代码正常工作并创建一个新的Api,以避免将来出现此问题。

字符数组也解决了你的问题

public Vararg8() {
            this(true, "test".toCharArray(), 4, 5, 6);
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM