I asked a question about differences between
public static <T> void work(Class<T> type, T instance);
and
public static <T, S extends T> void work(Class<T> type, S instance);
I think I should explain what exactly I want to know. Updating the original question is not proper for this time, I think, so I'm asking an another question here.
Say, I want to make a single reflected method for invoking those marshal
methods defined in Marshaller such as
void marshal(Object element, ContentHandler handler)
void marshal(Object element, File output)
void marshal(Object element, Node node)
and so on.
One of method that I'm working on is
void marshal(Object jaxbElement, Class<?> targetType, Object target)
The implementation is simple
- Find a method looks like
marshal(Ljava/lang/Object;Ljava/lang/Class;)V
withObject.class
andtargetType
- invoke the method with
element
andtarget
.
So any unit testing code can invoke like
marshal(element, ContentHandler.class, handler);
marshal(element, File.class, new File("text.xml"));
In this case how should I define the marshal
method? Is there any difference between
<T> marshal(Object element, Class<T> targetType, T target);
and
<T, S extends T> marshal(Object element, Class<T> targetType, S target)
?
Further Comments per Answers
I think I need the targetType
for fast and direct method looking the right method.
Without the targetType
I have to iterate all methods like
for (Method method : Marshaller.class.getMethods()) {
// check modifiers, name, return type, and so on.
if (!method.getParameterTypes()[1].isAssignableFrom(target.getClass())) {
}
}
Adding another version for this will be better, I think. :)
It's hard to know why you want the class object, because if you have an instance of
T
you can do this in the method:However, if you really need to pass a class, I think you want this:
By using
Class<? super T>
you achieve the flexibility of passing a Class that is a super class of the instance without the extra generic method parameter.If you assign the class at T, you don't need to feed it in the arguments, so
<T, S extends T> marshal(Object element, S target)
should be enough. But sinceS extends T
,S
can be recognized asT
.Unless you specifically need methods that are only in class
S
, you can omit it and writeHowever, since you are creating a generic method, you probably won't need to declare S. This for the following reason:
if the methods of S differ from T, there is no good way to determine the methods of several different classes of S. Unless they have a common interface, but then you might as well use the common interface as
T
.if the methods of S do not differ, there is not reason to specifically indicate it as generic operand.
There is no difference in what sets of arguments that
<T> marshal(Object element, Class<T> targetType, T target);
and
<T, S extends T> marshal(Object element, Class<T> targetType, S target)
can accept.
Therefore, if you are writing an API, you should prefer the simpler one, the one with fewer type parameters, i.e. the one without
S
.