泛型类型的反射声明

时间:2013-07-30 08:35:52

标签: java generics reflection

我问question

之间的差异
public static <T> void work(Class<T> type, T instance);

public static <T, S extends T> void work(Class<T> type, S instance);

我想我应该解释一下我想知道什么。我想这次更新原始问题是不合适的,所以我在这里问另一个问题。

说,我想制作一个反映方法,用于调用Marshaller中定义的marshal方法,例如

void marshal(Object element, ContentHandler handler)
void marshal(Object element, File output)
void marshal(Object element, Node node)

等等。

我正在研究的方法之一是

void marshal(Object jaxbElement, Class<?> targetType, Object target)

实施很简单

  1. 使用marshal(Ljava/lang/Object;Ljava/lang/Class;)VObject.class
  2. 查找类似targetType的方法
  3. 使用elementtarget
  4. 调用该方法

    因此任何单元测试代码都可以像

    一样调用
    marshal(element, ContentHandler.class, handler);
    marshal(element, File.class, new File("text.xml"));
    

    在这种情况下,我应该如何定义marshal方法?

    之间有什么区别吗?
    <T> marshal(Object element, Class<T> targetType, T target);
    

    <T, S extends T> marshal(Object element, Class<T> targetType, S target)
    

    每个答案的进一步评论

    我认为我需要targetType来快速直接地查找正确的方法。

    没有targetType我必须迭代所有方法,如

    for (Method method : Marshaller.class.getMethods()) {
    
        // check modifiers, name, return type, and so on.
    
        if (!method.getParameterTypes()[1].isAssignableFrom(target.getClass())) {
        }
    }
    

    我想,为此添加另一个版本会更好。 :)

3 个答案:

答案 0 :(得分:1)

如果您在T处分配课程,则无需在参数中提供课程,因此<T, S extends T> marshal(Object element, S target)应该足够了。但由于S extends TS可以被识别为T

除非您特别需要仅在类S中的方法,否则可以省略它并写入

<T> marshal(Object element, T target)

但是,由于您正在创建泛型方法,因此您可能不需要声明S.这是由于以下原因:

  • 如果S的方法与T不同,没有好的方法来确定几个不同类的S的方法。除非它们有一个共同的接口,但是你也可以使用公共接口作为{ {1}}。

  • 如果S的方法没有区别,则没有理由将其明确指出为通用操作数。

答案 1 :(得分:1)

很难知道为什么要使用类对象,因为如果你有T的实例,你可以在方法中执行此操作:

Class<T> targetType = target.getClass(); // class may be derived from the instance    

但是,如果你真的需要通过课程,我想你想要这个:

<T> void marshal(Object element, Class<? super T> targetType, T target) {

}

通过使用Class<? super T>,您可以灵活地传递一个Class,它是实例的超类而没有额外的泛型方法参数。

答案 2 :(得分:1)

的论证集没有区别

<T> marshal(Object element, Class<T> targetType, T target);

<T, S extends T> marshal(Object element, Class<T> targetType, S target)

可以接受。

因此,如果您正在编写API,则应该更喜欢更简单的API,即类型参数较少的API,即没有S的那个。