如何在给定泛型类型参数的情况下调用相应的方法?

时间:2015-09-16 09:06:37

标签: java generics

我有一个方法,通用类型T作为参数

private static <T> void doValidation(T[] pArray, int size, String firstName, String secondName) {

    ...

    for (int i = 0; i < size; i++) {

        ...

        validate(pArray[i]);
    }
}

然后我根据具体类型给出了不同的方法,例如AB等。

private static void validate(A a) {

}

private static void validate(B b) {

}

我希望它在运行时解析类型并根据类型调用相应的方法,是否可能?

目前我

no suitable method found for validate(T)
    method ValidateDataStructure.validate(A) is not applicable
      (argument mismatch; T cannot be converted to A)
    method ValidateDataStructure.validate(B) is not applicable
      (argument mismatch; T cannot be converted to B)
  where T is a type-variable:
    T extends Object declared in method <T>doValidation(T[],int,String,String)
----
(Alt-Enter shows hints)

它希望我当然可以演绎这个论点。

我正在尝试做一个Assimp的端口,我的意图是尽可能接近C结构。 This是我正在尝试移植的功能..

2 个答案:

答案 0 :(得分:1)

如果您要验证无法扩展的类型(例如IntegerString), 您可以实现自己的动态调度。例如,您可以创建这样的验证器映射(Java-8):

private static final Map<Class<?>, Consumer<?>> validators = new HashMap<>();

static {
    validators.put(A.class, (A a) -> validate(a));
    validators.put(B.class, (B b) -> validate(b));
    ...
}

并编写一个选择器方法:

static <A> Consumer<A> getValidator(Class<A> clazz) {
    // do nothing for unknown type
    return (Consumer<A>)validators.getOrDefault(clazz, () -> {});
}

最后你可以像这样使用它:

getValidator(value.getClass()).validate(value);

答案 1 :(得分:0)

根据您的确切需求,您的问题并不完全清楚,您有一些选择。

您可能实际上并不需要doValidation方法根据T采取不同的行为,而是根据运行时类型使用validate方法表现不同它的论点。这是一个有点不同的问题,但它很容易解决:最好的选择可能是让它委托给一个可覆盖的方法,如:

private static <T extends Validatable> void validate(T arg)
{
    arg.validate();
}

(当然,您需要定义适当的Validatable接口,并且doValidation方法中的T类型参数也需要声明为T extends Validatable)。

但是,上述选项要求您可以修改类AB(使它们实现Validatable)。从设计的角度来看,但没有这个限制,另一个选择并不是那么干净,而是通过引入validate方法来确定类型并相应地分配给不同的方法,如下所示:Object

private static void validate(Object arg)
{
    if (arg instanceof A) {
        validate((A) arg);
    }
    else if (arg instanceof B) {
        validate((B) arg);
    }
    else {
        throw new RuntimeException("Don't know how to validate object of class " + arg.getClass.getName());
    }
}