在Java中,我可以指定任意数量的泛型类型参数吗?

在Java中,我可以指定任意数量的泛型类型参数吗?,java,generics,Java,Generics,我希望用Java创建一种特殊类型的接口(尽管这同样适用于常规类)。这个接口需要包含一些方法,比如,invoke;根据提供的泛型类型参数,将使用不同数量的参数调用它 例如: public interface Foo<T...> { public void invoke(T... args); } // In some other class public static Foo<Float, String, Integer> bar = new Foo<Flo

我希望用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
    }
};
公共接口Foo{
公共无效调用(T…args);
}
//在别的班
公共静态Foo bar=newfoo(){
@凌驾
公共void调用(浮点arg1、字符串arg2、整数arg3){
//做任何事
}
};

简要解释,如何使用(并提供一些上下文),考虑类<代码>委托者< /代码>:该类采取不同数量的泛型类型,并使用这些参数类型有一个单独的方法-<代码>调用< /COD>。该方法将其参数传递给列表中的对象:采用相同泛型类型的

IDelegate
实例。这允许
Delegator
在多个委托方法(在
IDelegate
中定义)之间进行选择,而无需为每个特定的参数类型列表创建新类

有这样的吗?我已经阅读了有关C++的内容,但是在java中找不到类似的东西。有这样的东西吗?如果不是,那么最干净的方法是什么来模拟相同的数据模型

有这样的吗?我读过关于可变模板的书 在C++中,但是在java中找不到类似的东西。有这样的事吗 有空吗


不,此功能在Java中不可用。

不,没有类似的功能可以直接使用。但是,如果将库与
Tuple
类一起使用,则只需制作接口即可对其进行模拟

interface Foo<T> {
    void invoke(T t);
}

通过以这种方式嵌套元组类型,可以获得无限数量的参数。但是,这些变通方法非常难看,我不会使用它们。

鉴于您提供的上下文,我建议使用
列表作为参数。如果这些参数有共同点,您可以将列表限制为
,而不是使用
列表
。如果不是,您可能仍然希望使用标记接口

这里有一个例子

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;
    }
}
公共类主{
公共静态void main(字符串[]args){
代表(asList(新子女一(1)、新子女二(5)、新子女一(15));
}
私有静态无效委托(列表){
列表。forEach(项目->{
开关(项目类型){
案例一:委托人((ChildOne)项);中断;
案例二:授权二((ChildTwo)项;中断;
默认值:抛出新的UnsupportedOperationException(“类型不受支持:”+item.Type);
}
});
}
私有静态void delegateOne(ChildOne ChildOne){
System.out.println(“child-one:x=“+childOne.x”);
}
私有静态void delegateTwo(ChildTwo ChildTwo){
System.out.println(“child-two:abc=“+childTwo.abc”);
}
}
公共类父类{
公共最终类型;
公共父级(类型){
this.type=type;
}
}
公共枚举类型{
一,二
}
公共类ChildOne扩展了Parent{
公共最终int x;
公共儿童频道(int x){
超级(1型);
这个.x=x;
}
}
公共类ChildTwo扩展了Parent{
公开期末考试;
公共儿童2(国际abc){
超级(2型);
this.abc=abc;
}
}

此解决方案的最大缺陷是,子级必须通过enum指定其类型,该类型应与switch语句中的强制转换相对应,因此无论何时更改这两个位置之一,都必须记住更改另一个位置,因为编译器不会告诉您这一点。只有通过运行代码并执行特定的分支,您才会发现这样的错误,因此建议进行测试驱动开发。

换句话说:
Pair
就足够了。但是,由于没有人想要一对
,这样的问题通常会以不同的方式解决。要么完全删除类型安全性,要么使用类似的库
Foo<Tuple<String, Integer, Date, Pair<Long, BigDecimal>>> foo = ...
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;
    }
}