将List <object>分解为一组已知派生类型</object>的列表

时间:2014-06-03 01:16:26

标签: java downcast visitor-pattern

让我们说我有一个像List<Object> objectList这样的论点,它是从外部提供给我的,我完全无法控制。我们还要说,我知道此列表中每个元素的下载类型的每种可能性。例如,我们说我知道objectList包含这些类型的元素:int, String, double, boolean

我可以使用哪些方法将objectList过滤到每个下载类型的单独列表中,而不使用使用instanceof。所以对于这个例子,我想把objectList放到看起来像这样的东西:

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

所以说我想写一个看起来像这样的函数:

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

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

   return results;
}

我的研究很快引导我访问模式,但我得出的结论是我不能使用它,因为我需要控制objectList中存储的类型(或者至少能够将它们包含在内)我自己的派生类型),但这些是从外部来源提供给我的,因此访客模式似乎不可能(对吧?)。

对象列表中的派生类型的子集相当小(尽管实际上它比本例中的4大),并且这些类型正在改变。如果我需要编写多个专业化和调度员,那就没关系了。我试图避免任何类型的级联if / else或switch语句。

有没有办法专门化那些可以正确排序的函数?

3 个答案:

答案 0 :(得分:2)

不,通过List<Object> objectList,你告诉语言你放弃了比Object更具体的任何东西的类型安全性,这与Java中的一切有关。

您必须对要匹配的类型执行instanceof检查。你必须进行演员表演,因为这实际上是你正在做的事情 - 演员表演。围绕它的黑客不会有帮助。

答案 1 :(得分:1)

你可以尝试进行每次可能的演员表,如果没有失败,请将该元素添加到相关列表中。

然后你只需要捕获ClassCastException。但实际上:使用instanceof是最好的解决方案。

答案 2 :(得分:1)

另一种方法是使用Class.isInstance()方法而不是使用运算符instanceof。

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

为了使其更加灵活,您可以定义一个处理特定类的Handler基类,并使用您在objectList中支持的每种类型的特定处理程序的实例填充列表。

然后对于objectList中的每个对象,遍历您的处理程序列表,调用方法isHandling(),如果它是受支持的处理程序类型,则返回true。此方法将使用isInstance()方法检查类型。如果为true,那么您可以调用另一种方法来进行处理。这样,如果需要支持新类型,您只需为此类型派生一个新的处理程序,并将其注册到处理程序列表中即可。

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);
}