有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java 8中带varargs的构造函数歧义

在下面的类中,由于对this()的调用不明确,我得到了一个Java 8的编译错误。但是,使用Java6可以很好地编译这个类。 我知道我可以使用工厂方法之类的方法重构它,但是对于出现问题的实际类,我强烈希望现在维护当前的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);
    }
}

共 (5) 个答案

  1. # 1 楼答案

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

      public Vararg8() {
            this(true, "test",new int[]{ 4, 5, 6});
        }
    
  2. # 2 楼答案

    您可以通过传递一个显式的int[]数组来执行此操作:

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

    您可能会注意到,从某种意义上讲,这仍然是不明确的:您传递的内容仍然与Object...构造函数兼容。这样做的原因是方法解析分为不同的阶段,只有最后一个阶段才允许考虑varargs参数。因为您使用了显式数组,所以它可以很好地命中第二个数组,而不需要varargs扩展。如果没有varargs的扩展,它就不能命中第一个,所以直到最后阶段才会考虑

    the appropriate JLS docs

    The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

    The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

    The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

  3. # 3 楼答案

    试试这个:

    public Vararg8()
    {
      this(true, "test", new int[]{4, 5, 6});
    }
    
  4. # 4 楼答案

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

    如果您已经在使用对象类型,那么此解决方案将不花费任何费用

    这看起来像这样:

    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,这将在将来避免该问题

  5. # 5 楼答案

    字符数组也可以解决您的问题

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