方法原型中的varargs是否有多个对象类型?

问题描述

| 我正在尝试编写Java函数的原型,该原型可以用任意数量的整数和字符串调用
myMethod(1,2,3,\"Hello\",\"World\"); // Valid call
myMethod(4,\"foo\",\"bar\",\"foobar\"); // Valid call
理想情况下,我希望整数和字符串可以任何顺序给出(并可能混合使用):
myMethod(1,\"World\",3); // Valid call
我曾考虑使用varargs,但原型中只能有一个。我拥有的另一个想法是使用以下原型:
public void myMethod(Object ... objs) { [...] }
...但我认为,如果使用非预期类型的​​其他东西调用它,应该会出现编译错误。当然,可以执行运行时检查(
instanceof
),但这不是一个非常好的解决方案,对吗? 你会怎么做?     

解决方法

        Java编程语言中没有办法使其正常工作,因此您可以传递任意数量的字符串和整数,并在传递字符串或整数以外的其他内容时使编译器给出错误。     ,        如果您希望它是类型安全的,我可以这样做:
public myMethod(Thing<?>... thing) { ... }
然后创建您的Thing类:
public interface Thing<T> {
    public T value();
}

public class IntThing implements Thing<Integer> {
    private final int value;

    public IntThing(int value) {
        this.value = value;
    }

    public Integer value() {
        return value;
    }
}
我将让您想象一下如何编写StringThing。显然,使用比\“ Thing \”更好的名称,但是我帮不了你。 然后,您创建两个静态方法:
public static Thing<Integer> thing(int value) {
    return new IntThing(value);
}

public static Thing<String> thing(String value) {
    return new StringThing(value);
}
然后将每个对象包装在对
thing
的调用中:
myMethod(thing(1),thing(2),thing(3),thing(\"Hello\"),thing(\"World\"));
乱?对。不幸的是,Java无法像其他语言一样将这些内容隐藏起来。 Scala的隐式defs将在这里为您提供帮助,但这还带来了其他问题。就个人而言,我会进行
instanceof
检查,但这将确保您的代码在编译时是安全的。     ,        无法使用泛型来匹配两种类型,例如
public <T extends String | Integer> void myMethod(T... objs); // You can\'t do this
    ,        您所描述的问题的唯一可能解决方案是已经说明的问题,该函数接受类型为
Object
的varargs参数。这是由于Java中的限制,即方法签名中只能有一个vararg,并且它必须是最后一个参数。 在不知道您打算12英镑做什么的细节的情况下,很难说出替代性的优雅解决方案可能是什么。     ,        (解决方法) 添加到您的库中:
package mylib;

public class Lang {
    public static <T> T[] varargs (T...ts) {
        return ts;
    }
}
在您的程序中:
package myprog;

import static mylib.Lang.*;

public class MyProg {

    public static void testfunc (Integer[] ints,String[] strs) {

        for (int i : ints)
            System.out.println(i);

        for (String s : strs)
            System.out.println(s);
    }

    public static void main (String[] args) {
        testfunc(
            varargs(1,2,3),varargs(\"Sophia\",\"Jacob\")
        );
    }
}
(打破了许多编码风格规则)     ,        允许语法
public class Foo<T extends Number & List> {
  ...
}
类型变量“ 16”允许类型相同的类型是“ 17”和“ 18”的子类型(例如,实现多个接口的类型)。