… (or More on cast away with Java generics)
Question: How many times did you encounter this kind of code?
List<Element> l = ...;
for (Element e : l) {
if (e instanceof SubElement) {
SubElement se = (SubElement) element;
// do something
}
}
If you get that so often, what do you think about this code?
List<Element> l = ...;
for (SubElement se : filter(l)) {
// do something
}
Nice, huh?
I came across this idea after reading an article Cast away with Java generics. The article suggests a nice approach to cast.
@SuppressWarnings("unchecked") public static <X> X cast(Object o) {
return (X) o;
}
And then you can use it to change an ugly code of:
Session webappSession;
Map<String, Map<String, Collection<Entity>>> myUglyMap = (Map<String, Map<String, Collection<Entity>>>) (webappSession
.getAttribute("myUglyMap"));
to a slightly better code:
Session webappSession;
Map<String, Map<String, Collection<Entity>>> beautiful = cast(webappSession.getAttribute("beautiful"));
To get the nice iteration like I presented in the beginning of the article, I created two methods that reuse this cast method. Here they are:
public static <X, T extends X> Iterable<T> filter(final Iterable<X> iterable) {
return new Iterable<T>() {
@Override public Iterator<T> iterator() {
return new Iterator<T>() {
private T t = null;
@Override public boolean hasNext() {
while (iterable.iterator().hasNext()) {
try {
t = cast(iterable.iterator().next());
return true;
} catch (ClassCastException e) {}
}
return false;
}
@Override public T next() {
if (t == null) {
while (iterable.iterator().hasNext()) {
try {
return cast(iterable.iterator().next());
} catch (ClassCastException e) {}
}
}
return t;
}
@Override public void remove() {
iterable.iterator().remove();
}
};
}
};
}
public static <X, T extends X> Iterable<T> filter(final X[] iterable) {
return new Iterable<T>() {
@Override public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
@Override public boolean hasNext() {
while (index < iterable.length) {
try {
@SuppressWarnings("unused")
T element = cast(iterable[index]);
return true;
} catch (ClassCastException e) {}
index++;
}
return false;
}
@Override public T next() {
while (index < iterable.length) {
try {
return cast(iterable[index++]);
} catch (ClassCastException e) {}
index++;
}
return null;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
The down side is of course you may have problem with performance because of ClassCastException. But I haven’t profiled it… yet.







