Java,通用启用对象列表的隐式和显式类型转换

时间:2011-03-15 15:00:01

标签: java generics

在使用Java和数据库时,我总是想知道一件事。我使用数据库抽象层并得到我的结果:

Hashtable h = connection.selectRow("select * from table where id = 5");

但是,当以相同的格式返回多个行时,它会返回:

ArrayList<Hashtable> a = connection.selectAll("select * from table where id > 5");

现在,因为我喜欢泛型,我想通过使用

来充分利用它
ArrayList<Hashtable<String,String>> a = connection.selectAll("select * from table where id > 5");

但这不会编译:

Cannot convert from ArrayList<Hashtable> to ArrayList<Hashtable<String,String>>.

然而,像这样分开,它起作用:

ArrayList<Hashtable> a = connection.selectAll("select * from table where id > 5");
Hashtable<String,String> h = a.get(0);

这只会产生类型安全警告:

Type safety: The expression of type Hashtable needs unchecked conversion to conform to Hashtable<String,String>.

似乎上面的这一步与这两行相同,但是将它们混合成一个Java拒绝进行转换。我怀疑有一些内部机制负责这种行为,但尚未找到原因。

有人愿意详细说明吗?

编辑:只是为了澄清。在我的示例中,错误消息显示

Cannot convert from ArrayList<Hashtable> to ArrayList<Hashtable<String,String>>.

当在下面的行中时,Java似乎非常有能力它只是告诉我它在我使用时无法做到

Hashtable<String,String> h = a.get(0);
在我看来,Java对我说谎。当然,不是故意的,我们彼此喜欢。但必须有一个理由。这就是我想要找到的。

4 个答案:

答案 0 :(得分:1)

connection.selectAll()的返回类型为ArrayList<Hashtable>。这就是左侧必须要做的事情。

因此,当你说

ArrayList<Hashtable> a = connection.selectAll("select * from table where id > 5");
Hashtable<String,String> h = a.get(0);

你收到警告。 a.get(0)正在返回Hashtable(非通用),您将其分配给Hashtable<String,String>

答案 1 :(得分:0)

这里存在多个问题/缺陷。

  1. Hashtable已同步。除非确实需要同步映射,否则不建议使用Hashtables。您可以改为使用Collections.synchronizedMap

  2. 您的实体型号错误。不应将Map数据结构用于此类操作。相反,您应该为每个表创建一个实体。如果表是关于员工的,则创建一个名为Employee的类,其中不同的属性映射到数据库中的列。

  3. connection.select*方法似乎没有通用化,这意味着您不能只在方法调用的左侧使用泛型。

  4. 总而言之,创建connection个对象实例的类是不对的。

答案 2 :(得分:0)

作为临时解决方案,我认为您实际上可以输入类似

的类
public class yourConnectionClass<E>

在该课程中,您可以更改方法的Returntyoe:

public <E> HashMap<E,E> selectAll()

如果您现在创建类的对象:

connection = new yourConnectionClass<String>();

我认为这应该有效,以便该方法的返回类型现在应该是Hashmap<String,String>

我真的希望有所帮助。

答案 3 :(得分:0)

http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.8

  

VectorVector<String>的分配是不安全的(因为原始向量可能具有不同的元素类型),但仍然允许使用未经检查的转换(第5.1.9节)以启用接口遗留代码

原始类型的支持是半生的;像这样的一些简单案例可以轻松过渡。