【问题标题】:Storing different parameterized types in the same generic arraylist in Java在 Java 中将不同的参数化类型存储在同一个泛型数组列表中
【发布时间】:2013-06-01 09:04:11
【问题描述】:

我喜欢在 java 中创建数据库表的类表示。 列被设计为通用类,以便它可以处理表列可能具有的所有不同数据类型。

public class TableColumn<T> {
    ...
}

一个表有 0 ... n 个 TableColumns,所以我的表类看起来像这样:

public class Table {
    protected ArrayList<TableColumn<T>> columns =
                new ArrayList<TableColumn<T>>();
    ...
}

想法是通过以下方式添加列。

Table t = new Table();
t.addColumn(String.class);
t.addColumn(Integer.class);
t.addColumn(Date.class);
t.addColumn(String.class);

然后我可以通过以下方式操作数据:

String a = t.Cols(2).Row(3);
t.Col(2).Row(3) = "b";

但是我目前的实现方式正在失去类型安全性......我的问题是如何实现列,因为列可能会获得不同的数据类型。

有人有线索吗?

【问题讨论】:

  • 所以您希望col(2)col(3) 属于不同类型?那是不可能的。仅仅因为类型检查发生在编译时,参数 values 对这些没有影响。
  • 还有其他可行的方法吗?另一个概念另一个结构?
  • 你可以通过一个&lt;T&gt; T get() 方法来伪造这个,该方法只是转换为T。这将允许 String x = foo.get()Integer x = foo.get() 编译。但这也是缺点:您丢失了所有编译时类型检查。当您使用错误时,它只会在运行时崩溃并烧毁。
  • 太糟糕了,我绝对想保持类型安全。

标签: java generics parameterized-types


【解决方案1】:

为什么不为每个表创建一个不同的对象呢?比如:

具有字段的类玩家:

String name;
int points;
int number;

带田野的班级体育场:

String location;
Date dateBuilt;

带字段的班级团队:

String name;
ArrayList<Players> roster;

然后您可以将所有值保存在一个列表或数组列表中,并让它们由数据库表分隔,而不必猜测您在哪个表中。您必须保存更多对象,但您会能够了解更多您正在处理的问题。

【讨论】:

  • 问题是我不知道我的表会有多少列,也不知道它们不是哪种类型...
【解决方案2】:

如果类型组合数量有限,您可以使用接口作为这些组合。这将使您能够以相同的方式存储列,并且您不需要任何特殊的转换。

t.addColumn(MyInterface.class);

另一种方法,它仍然不会像你想要的那样干净,但有点不可避免,是使用一个新的类,它可以让你承担一些强制转换和类型检查的负担。

例子:

public static class MyWrapper{
    Class<?>[] validPossibleClasses;
    Object o;
    public MyWrapper(Class<?> ...classes){
        this.validPossibleClasses = classes;
    }
    public boolean validateClass(Class<?> clazz){
        for (Class<?> c : validPossibleClasses){
            if (!c.isAssignableFrom(clazz))
                return false;
        }
        return true;
    }
    public void set(Object o) throws Exception{
        if (!validateClass(o.getClass()))
            throw new Exception("Bad Cast");
        this.o = o;
    }
    public String getString(){
        return (String) o;
    }
    public Integer getInt(){
        return (Integer) o;
    }
    ...
    // more specific getters
}

用法应该是这样的

String a = t.Cols(2).Row(3).getString();
t.Col(2).Row(3).set("b");

【讨论】:

  • 你能详细解释一下吗?
  • 等等,您是否正在寻找另一种存储列的方法?还是在一列中使用多种类型时遇到问题?
  • 两者。起初,我想在一列中使用多种类型而不会失去类型安全性。如果这不可能,另一种方法会很棒。
猜你喜欢
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 2012-07-03
相关资源
最近更新 更多