获得泛型类型的实际类型<t,s> </t,s>

时间:2014-12-03 13:07:08

标签: java generics javafx

我应该创建一个新的Object,它扩展了JavaFX中TableView的功能(让我们称之为TableViewPlus - 我没有更好的名字,但是大声笑)。一个新功能应该是每个TableColumn的过滤器,取决于列中的类型。

例如:我有类型&#34; Person&#34;的对象,其中包含名称(String)的字段,出生日期(LocalDate)和ID(整数)。这些是在我的TableViewPlus之外定义的,只是使用以下方法传递给它:

public void addColumns(TableColumn<T, ?>... columns) {
    table.getColumns().addAll(columns);
}

稍后,我想为每个表添加过滤器(作为上下文菜单)。对于name列,我需要一个带有简单字符串匹配的过滤器,对于日期列,我需要一个带有datepicker的过滤器,依此类推......现在问题是:如何判断我的列中的数据类型是什么? (我怎么知道哪种类型&#39;?&#39;是?)。

我的解决方案如下,只有在表格中已有数据时才有效:

private void createFilters() {
    for (TableColumn<T,?> col : table.getColumns()) {
        if (col.getCellData(0).getClass().equals(String.class) {
            //create string filter
        } else if (col.getCellData(0).getClass().equals(Integer.class) {
            //create int filter
        } else if (col.getCellData(0).getClass().equals(LocalDate.class) {
            //create date filter
        }
    }
}

显然这很糟糕! :d


如果不能直接使用给定的东西,另一种可能的解决方案可能是直接用列创建过滤器。所以我不会让TableColumns传递给我的TableViewPlus,只是一个名字和一个回调,就像这样:

public <S> void test(String name, Callback<TableColumn.CellDataFeatures<T,S>,ObservableValue<S>> value) {
    TableColumn<T,S> col = new TableColumn(name);
    col.setCellValueFactory(value);
    table.getColumns().add(col);
    //if (S == String.class) {} //this line does not work because "Cannot find Symbol: variable S"
}

此方法到目前为止工作正确地创建了列并填充了数据(因此S以某种方式正确设置)并且我从上面的createFilters()方法得到相同的结果,但这只是使用表中的第一项再次。我如何获得S的课程?

3 个答案:

答案 0 :(得分:1)

您实际需要的是 type token 。如果要独立访问该类型,请将类型标记传递给类的构造函数。

这是一个简化的示例,您可以轻松地使用自己的类:

public class Generified<T> {
    private T value;
    private Class<T> typeToken;

    public Generified(Class<T> typeToken) { this.typeToken = typeToken; }
    public T get() { return value; }
    public void set(T value) { this.value = value; }
    public void someMethod() { System.out.println(typeToken.getName()); }

    public static void main(String[] args) {
        Generified<Integer> generified = new Generified<>(Integer.class);
        generified.someMethod();
    }
}

运行此程序将生成输出

  

java.lang.Integer中

请注意,您仍然具有类型安全性。以下代码 - 例如 - 将无法编译:

Generified<Integer> generified = new Generified<>(String.class);

答案 1 :(得分:0)

你想要的是不可能的。在Java中,泛型只在编译时出现 。编译代码后,每个类型参数基本上都成为Object引用。因此,在朗姆酒时,不可能再找出泛型类型的类型参数。这称为类型擦除。这对于较新的Java版本是向后兼容的是必要的。

一个解决方案是明确存储某处内容的类型。 Class是Java中的普通类,因此您可以使用此类型的字段。

答案 2 :(得分:0)

您可以这样做:

private final Map<TableColumn<T,?>, Class<?>> columnTypes = new HashMap<>();

public <S> void addColumn(TableColumn<T,S> col, Class<S> type) {
    getColumns().add(col) ;
    columnTypes.put(col, type);
}

现在,您可以在需要时检索列的类型,并按照

的方式执行操作
if (columnTypes.get(col) == String.class) {
    // create String filter...
}

它并不漂亮,但它比假设所有表都有数据并且数据类型都相同更好。