问题描述
|
我正在尝试编写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”的子类型(例如,实现多个接口的类型)。