I am using a heterogeneous container similar to this one. I can put and receive objects from the container with ease:
Favorites f = new Favorites();
f.putFavorite(String.class, "Java");
String someString = f.getFavorite(String.class);
But there seem to be no easy way to iterate over such container. I can add a keySet()
method to the Favorites
class and simply return the key set of the internal Map
object:
public Set<Class<?>> keySet() {
return favorites.keySet();
}
Now, I would like to iterate over the keys, use the keys to get the associated values, and call some methods on the received objects:
for (Class<?> klass : f.keySet()) {
// f.getFavorite(klass).<SOME_METHOD_SPECIFIC_TO_THE_CLASS-KEY>
}
I thought that I could access the methods of the objects held in my container by calling klass.cast(f.getFavorite(klass)).SOME_METHOD()
, but it doesn't work either (meaning, I cannot access any methods except for the Object
-related methods).
Let's say, that in my use case I would like to inspect the interfaces of all these objects I iterate over and act accordingly to the detected interface. Let's also assume that I may have dozens of objects of various classes and all of them implement one of three interfaces.
The only solution I can think of is to stuff my code with dozens of isinstance
checks, but I would prefer a less cumbersome approach (i.e. checking if a given object implements one of three interfaces).
By trying to call a specific method on each entry, you are basically saying that you know better than the compiler, and that you know each entry has a specific super class.
If you know that's the case, you can use Class#asSubclass
to type klass
as Class<? extends KnownSuper>
so that getFavorite
will then return a subclass of KnownSuper
(and therefore expose the method):
Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod()
for (Class<?> klass : f.keySet()) {
f.getFavorite(klass.asSubClass(superClass)).callMethod()
}
However, this will obviously give a runtime exception if one of the key classes does not extend KnownSuper
. So if the above would be safe, you should parameterize your heterogeneous container to only accept key classes that extend from KnownSuper
in the first place.
If not all entries will be of this type, you could also check first if the key is suitable when iterating:
Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod()
for (Class<?> klass : f.keySet()) {
if (superClass.isAssignableFrom(klass)) {
f.getFavorite(klass.asSubClass(superClass)).callMethod()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With