2014-09-02 70 views
0

我有一个泛型类型CHILDITEMS的ObservableList,其中<CHILDITEMS extends PlanItem>。我如何知道在运行时ObservableList是什么类型?ObservableArrayList:如何通过反射获取通用类型?

/*Get a reference to the child items of the currently viewed item.*/ 
    ObservableList<CHILDITEMS> childItems = (ObservableList<CHILDITEMS>) viewing.getChildItems(); 
    /*Set the child items label to the type of the child items.*/ 
    childItemsLabel.setText("Name of CHILDITEMS class"); 

我不能使用getFields,因为CHILDITEMS不是一个真正的字段。在ObservableList.class上使用getType只返回泛型类型“E”,而不是运行时的内容。

CHILDITEM类型可能是目标,目标,策略或任务。我想知道它在运行时是什么。

+1

泛型是一个编译时构造。那就是编译器会用它们来检查你是否没有意外地使用Object。在运行时,您的'ObservableList '变成'ObservableList '。在引擎盖下,它将像使用Java的预泛型版本一样使用强制转换。这意味着如果不进行大量'instanceof'测试,就无法做到自己想做的事。 – Romski 2014-09-02 00:41:17

回答

0

正如@Romski在评论中所说,这些信息甚至在运行时都没有保留。

如果你知道你的列表是非空的,你只把确切类型的项目在列表中(即你的ObservableList<P>只包含运行时类型P的项目,而不是是P子类的实例任何物品),那么你当然可以做list.get(0).getClass(),但这是不太可能的情况,并不是非常健壮。

您也可以考虑为列表创建一个包装,使用类型标记来保留该类型。喜欢的东西:

public class TypedObservableList<P extends PlanItem> { 
    private final Class<P> type ; 
    private final ObservableList<P> list ; 

    public TypedObservableList(Class<P> type) { 
     this.type = type ; 
     this.list = FXCollections.observableArrayList(); 
    } 

    public Class<P> getType() { 
     return type ; 
    } 

    public ObservableList<P> getList() { 
     return list ; 
    } 
} 

现在你结束了大量的代码看起来像

TableView<Goal> goalTable = new TableView<>(); 
TypedObservableList<Goal> goals = new TypedObservableList<>(Goal.class); 
goalTable.setItems(goals.getList()); 

,但至少你现在可以做

TypedObservableList<? extends PlanItem> typedList = viewing.getChildItems(); 
childItemsLabel.setText(typedList.getType().getSimpleName()); 

你还没说什么viewing是,但你也许可以想出类似的解决方案,在那个类中持有类型令牌,所以你最终会得到

childItemsLabel.setText(viewing.getChildType().getSimpleName()); 
+0

这是一个有点破解的解决方案,但是由于Java的当前局限性,这是我能做的唯一的事情。 – 2014-09-03 07:13:00