In generic method <T> doSth(List<T> l), check whether T implements Comparable?
The title basically says it all: if I have a java method that is generic in T, can I find out anything about T? In particular, can I check whether T implements a certain interface or extends a certain class?
I would like to do something like
public <T> List<T> doSth(List<T> l) {
if(T extends Comparable) {
// do one 开发者_JAVA技巧thing
} else {
// do another
}
return l;
}
Any hints?
Thanks a lot,
Johannes
It's not clear whether you want to perform the check at compile-time or at runtime. If you simply want to ensure that the list parameter passed to the method contains certain types of objects, then redefine T
appropriately.
For example, to ensure that the compiler will only allow a List<Comparable>
to be passed to this method, redefine T
as:
public <T extends Comparable<? super T>> List<T> doSth(List<T> l) {
// Method body omitted
}
You can then use method-overloading (instead of an if-else statement), to ensure the correct code is called for any value of T
. In other words, replace this:
public <T> List<T> doSth(List<T> l) {
if(T extends Comparable) {
// do one thing
} else {
// do another
}
return null
}
with these:
public <T extends Comparable<? super T>> List<T> doSth(List<T> l) {
// do one thing
return null;
}
public <T> List<T> doSth(List<T> l, Class<T> clazz) {
// do another
return null;
}
However, you need to remember choosing which overloaded method to call and generic-type checking is compile-time only! For example, the following code:
List<? extends Serializable> alist = new ArrayList<Integer>();
doSth(alist);
will actually call the second doSth
method, because the compile-time type parameter (? extends Serializable
) does not implement Comparable
, even though the runtime type parameter (Integer
) does.
No - due to type erasure. At execution time, you don't know the type of T at all.
One option would be to specify the type as another parameter:
public <T> List<T> doSth(List<T> l, Class<T> clazz) {
if (Comparable.class.isAssignableFrom(clazz)) {
...
}
}
yes, you can:
public <T> List<T> doSth(List<T> l) {
//You could also check every element, if there is a chance only some will be comparable
if (l.size() >0 && l.get(0) instanceof Comparable) {
// do one thing
} else {
// do another
}
return l;
}
Note that you are checking what type the elements in "l" are, NOT T - that is the key.
Edit: Changed the code to handle the fact that it was a list - I had missed that in my original reading.
You should already know at (even before! :) compile time whether T extends Comparable or not, so why not make two methods?
public <T extends Comparable<T>> List<T> doSthComp(List<T> l) {
// do one thing
return l;
}
public <T> List<T> doSth(List<T> l) {
// do another
return l;
}
You can do a
public <T extends Comparable<T>> List<T> doSth(List<T> l)
which will allow you to use the Comparable interface on items in 'l'
Well for compile time check Don already gave an answer. For the runtime it's only possible if you also pass a explicit object representing T, for example:
static <T> List<T> doSth(List<T> l, Class<T> tClass)
having tClass object representing real class of T you can check if it have implemented comparable via reflection. But compile-time check is much, much better from my point of view.
精彩评论