Java implements erasure, so there’s no way to tell on runtime if genericObject
is an instance of Set<String>
or not. The only way to guarantee this is to use bounds on your generics, or check all elements in the set.
Compile-time Generic Bounds
Using bounds checking, which will be checked at compile-time:
public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
// Do something with tSet here
}
Java 8
We can use streams in Java 8 to do this natively in a single line:
public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (set.stream().allMatch(String.class:isInstance)) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}
Java 7 and older
With Java 7 and older, we need to use iteration and type checking:
public <T> void genericMethod(T t) {
Set<String> strs = new HashSet<String>();
Set<?> tAsSet;
if (t instanceof Set<?>) {
tAsSet = (Set<?>) t;
for (Object obj : tAsSet) {
if (obj instanceof String) {
strs.add((String) obj);
}
}
// Do something with strs here
} else {
// Throw an exception or log a warning or something.
}
}
Guava
As per Mark Peters’ comment below, Guava also has methods that do this for you if you can add it to your project:
public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (Iterables.all(set, Predicates.instanceOf(String.class))) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}
The statement, Iterables.all(set, Predicates.instanceOf(String.class))
is essentially the same thing as set instanceof Set<String>
.