我希望在Java 中创建一种特定类型的接口(尽管这同样适用于常规类)。这个接口需要包含一些方法,比如invoke
;它将使用不同数量的参数调用,具体取决于提供的泛型类型参数。
举个例子:
public interface Foo<T...> {
public void invoke(T... args);
}
// In some other class
public static Foo<Float, String, Integer> bar = new Foo<Float, String, Integer>() {
@Override
public void invoke(Float arg1, String arg2, Integer arg3) {
// Do whatever
}
};
简要说明如何使用(并提供一些上下文),考虑一个类Delegator
:该类采用不同数量的泛型类型,并且只有一个方法 - invoke
,包含这些参数类型。该方法将其参数传递给列表中的对象:IDelegate
的实例,它采用相同的泛型类型。这允许Delegator
在几个委托方法(在IDelegate
中定义)之间进行选择,而不必为每个特定的参数类型列表创建新类。
有这样的可用吗?我在C ++中已经阅读了variadic templates,但在Java中找不到类似的东西。有这样的东西吗?如果不是,那么模拟相同数据模型的最简洁方法是什么?
答案 0 :(得分:4)
有这样的可用吗?我读过有关可变参数模板的内容 在C ++中,但在Java中找不到类似的东西。有没有这样的事情 可用?
不,这个功能在Java中不可用。
答案 1 :(得分:2)
不,没有直接可用的东西。但是,如果您使用具有Tuple
类的库,则可以通过创建接口来模拟它
interface Foo<T> {
void invoke(T t);
}
(此界面与Consumer<T>
基本相同。)
然后你可以做例如
Foo<Tuple<String, Integer, Date, Long>> foo = new Foo<>() {
...
}
每个参数数量都需要单独的Tuple
类型。如果您有4个参数的Tuple
类,但不是5个参数,则可以使用Pair
类来挤压额外的参数。
Foo<Tuple<String, Integer, Date, Pair<Long, BigDecimal>>> foo = ...
通过以这种方式嵌套元组类型,您可以获得无限数量的参数。但是,这些变通办法非常难看,我也不会使用它们。
答案 2 :(得分:2)
根据您提供的上下文,我建议您使用List
作为参数。如果这些参数有共同点,您可以将列表限制为<T extends CommonParrent>
,而不是使用List<Object>
。如果没有,您可能仍然想使用标记界面。
这是一个例子。
public class Main {
public static void main(String[] args) {
delegate(asList(new ChildOne(1), new ChildTwo(5), new ChildOne(15)));
}
private static <T extends Parent> void delegate(List<T> list) {
list.forEach(item -> {
switch (item.type) {
case ONE: delegateOne((ChildOne) item); break;
case TWO: delegateTwo((ChildTwo) item); break;
default: throw new UnsupportedOperationException("Type not supported: " + item.type);
}
});
}
private static void delegateOne(ChildOne childOne) {
System.out.println("child one: x=" + childOne.x);
}
private static void delegateTwo(ChildTwo childTwo) {
System.out.println("child two: abc=" + childTwo.abc);
}
}
public class Parent {
public final Type type;
public Parent(Type type) {
this.type = type;
}
}
public enum Type {
ONE, TWO
}
public class ChildOne extends Parent {
public final int x;
public ChildOne(int x) {
super(Type.ONE);
this.x = x;
}
}
public class ChildTwo extends Parent {
public final int abc;
public ChildTwo(int abc) {
super(Type.TWO);
this.abc = abc;
}
}
这个解决方案的最大缺陷是,孩子必须通过enum指定他们的类型,这应该与switch语句中的强制转换相对应,所以每当你改变这两个地方中的一个时,你将不得不记得改变另一个,因为编译器不会告诉你这个。您只能通过运行代码并执行特定分支来找到这样的错误,因此建议使用测试驱动开发。