In general, you can't do that. The collection may be empty or composed only of null values for example. Also, what about interfaces? there may be multiple interfaces which are common to all of the collection elements.
However, maybe one of the following will be helpful in your case:
1) Analyzing the collection contents: Assuming the collection is non-empty, scan all items in the collection and find their lowest common ancestor in the class hierarchy.
2) Getting the generic declared type: If the object you are inspecting is declared as a data member (with generics) of some class, you can evaluate its declared generic type at runtime, using reflection (see Field.getGenericType())
-- EDIT --
Just for practicing, I implemented the lowest common ancestor utility:
public static Class<?> getLCA(Collection<?> c) {
Class<?> res = null;
for (Object obj : c)
if (obj != null) {
Class<?> clazz = obj.getClass();
res = (res == null)? clazz : getLCA(res, clazz);
}
return res;
}
private static Class<?> getLCA(Class<?> classA, Class<?> classB) {
if (classA.isAssignableFrom(classB))
return classA;
if (classB.isAssignableFrom(classA))
return classB;
while (!classA.isAssignableFrom(classB))
classA = classA.getSuperclass();
return classA;
}
Efficiency: O(n*h), where n is the collection size and h is the maximum depth of the collection items in the class hierarchy.