Question

Let's say that I have an argument like List<Object> objectList, which is provided to me externally, and that I have absolutely no control over. Let's also say that I know every single possibility for the downcasted types of each element in this List. For example, let's say I know that objectList contains elements of these types: int, String, double, boolean.

What approaches could I use to filter objectList into separate lists of each downcasted type without using instanceof. So for this example, I want to put objectList into something that looks like this:

class SpecificTypes
{
   List<Integer> intList;
   List<String> stringList;
   List<Double> doubleList;
   List<Boolean> booleanList;
}

So say I want to write a function that looks like this:

SpecificTypes filterObjectList(List<Object> objectList)
{
   SpecificTypes results = new SpecificTypes();

   // Populate 'results' somehow
   // Without using cascading if/else or switch logic

   return results;
}

My research quickly led me to the visitor pattern, but I have come to the conclusion that I cannot use this because I would need control over the types stored in objectList (or at least be able to wrap them in my own derived types), but these are supplied to me from an external source so the visitor pattern seems impossible (right?).

The subset of derived types in the object list is fairly small (although in reality it's larger than the 4 in this example), and those types will not be changing. So it's OK if I need to write multiple specializations and dispatchers. I am trying to avoid any sort of cascading if/else or switch statement.

Is there some way to specialize functions that would sort these out properly?

Was it helpful?

Solution

No, by List<Object> objectList you are telling the language you forfeit type safety of anything that is more specific than Object which is about everything in Java.

You have to perform instanceof checks on the types you want to match. You have to perform casts because this is effectively what you're doing - casting. Hacks around it won't help.

OTHER TIPS

You could try to do each possible cast, and if it don't fail add that element to the relevant list.

Then you just need to catch the ClassCastException. But really: Using instanceof is the best solution.

Another way to do it is using the Class.isInstance() method instead of using the operator instanceof.

if (Boolean.class.isInstance(obj)){
  // handle this type
}

To make it more flexible, you could define an Handler base class which handles a specific class and populate a list with an instance of a specific handler for each type you support in your objectList.

Then for each object in objectList you iterate through your list of handlers calling a method isHandling() which would return true if its the supported type of the handler. This method would use the isInstance() method to check the type. If true, then you could call another method to do the handling. That way, if a new type needs to be supported you only have to derive a new handler for this type and register it in the list of handlers and that's it.

public abstract class Handler {

  protected Class<?> type;

  protected Handler(Class<?> type) {
    this.type = type;
  }

  public boolean isHandling(Object obj) {
    return type.isInstance(obj);
  }

  public abstract void handle(Object obj);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top