Reputation: 21998
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
marshal(Ljava/lang/Object;Ljava/lang/Class;)V
with Object.class
and targetType
element
and target
.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. :)
Upvotes: 0
Views: 178
Reputation: 122449
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
.
Upvotes: 1
Reputation: 425043
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:
Class<T> targetType = target.getClass(); // class may be derived from the instance
However, if you really need to pass a class, I think you want this:
<T> void marshal(Object element, Class<? super T> targetType, T target) {
}
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.
Upvotes: 1
Reputation: 1678
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 since S extends T
, S
can be recognized as T
.
Unless you specifically need methods that are only in class S
, you can omit it and write
<T> marshal(Object element, T target)
However, 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.
Upvotes: 1