1

我正在重构一个本土的 DAO 容器,希望使该类具有通用性。它在内部使用 anArrayList来存储检索到的对象。

此类的一种用法是将容器的列表放入请求范围,并且由于 Websphere 的限制,我无法将泛型传递List<Foo>给请求范围(Websphere 不处理开箱即用的泛型)

如果我继续进行重构,我将需要将其转换/转换List<Foo>为非泛型List对象..

// Boils down to this...
List<Foo> listFoo = new FooListing().findAllFoo();
List listThings = listFoo;
request.setAttribute("listThings", listThings);

像这样逆转泛型有什么影响?我应该避免做这种操纵吗?

编辑:代码片段很冗长,以明确展示我所描述的内容..

4

5 回答 5

3

如果 List 的组件类型与预期类型匹配,则没有问题。

Java 中的泛型仅用于编译器的类型检查,它们在运行时不起作用。如果您使用的是不支持泛型的旧库,则别无选择,只能忽略泛型类型。事情应该继续工作,因为该系统的设计考虑了向后兼容性。

所以你失去的只是编译时类型检查(它让你回到 Java 1.4 的位置,这意味着,如果类型匹配,一切都会正常工作,如果不匹配,你会在运行时得到 ClassCastExceptions 或其他不需要的行为)。

但是,我认为你可以写

request.setAttribute("listThings", listFoo);

此方法采用任何类型的对象。即使它想要一个列表,你仍然可以传递一个List<Foo>(它仍然是一个列表)。

于 2010-03-11T06:18:49.813 回答
2

Java 对泛型使用“类型擦除”——本质上这意味着编译器会检查泛型,但运行时会忘记它,只是将其视为对象列表。*

每当您将 aList<Foo>视为一个列表时,您都不会获得编译器检查以确保您没有将 Bla 放入您的列表中。因此,如果您调用List<Foo>.get()它,您可能会得到一个 ClassCastException,结果证明它是一个隐藏在列表中的 Bla。但这只有在您的某些代码将 Bla 放入您的列表时才会发生。

如果您不想谨慎,那么如果您将List<Foo>作为 List 传递给任何可能将非 Foo 添加到列表中的东西,请不要List<Foo>在访问时将其视为 a ,而是将其视为Objectsand的列表添加 instanceof 检查。

*一些信息可以在运行时访问,但我们不要让事情复杂化。

于 2010-03-11T06:25:24.057 回答
1

泛型类型的“非泛型”版本称为“原始类型”。

传递请求原始等效项的泛型类型通常是可以的。这实际上是 Java 中泛型以它们的方式工作(使用擦除)的主要原因:实现“泛型”代码和预泛型代码之间的互操作性。

您需要注意的主要事情是,如果您将 a 传递给要求 aList<Foo>的东西List,他们可能会将非Foo对象放入List. 你不会得到任何编译时间检查来帮助你。你确实得到了一些运行时检查:当你使用一个在你的上返回 a并且它必须返回一个非 -ClassCastException的方法时,将抛出a 。FooList<Foo>Foo

如果您想要更多快速失败的行为,您可以包装您的List<Foo>withCollections.checkedList()以获得一个 List ,它将检查插入时元素的类型。

Foo如果它本身是泛型类型,事情会变得更加复杂。运行时检查仅对具体类型进行(即:删除了泛型类型参数的类型),所以如果你给他们 aList<Set<Bar>>并且他们插入 aSet<Baz>或只是 a Set,你不会知道,因为元素的运行时/具体类型是Set任何一种方式.

于 2010-03-11T06:33:04.760 回答
0

首先,您不能将泛型转换为非泛型列表,所以是的,您必须将其转换。

其次,泛型列表的两个主要优点是 1) 它确保所有对象都属于指定的类型,以及 2) 它允许您直接访问对象集合的方法而无需重铸它们。这使您可以编写更清晰的代码,并节省一些处理周期,而不必进行回退和第四次转换。

然而,这些优势中的任何一个都不是迫切需要的。如果您不能使用它们,您将不会注意到性能差异。不过,您的代码可能看起来有点混乱。

于 2010-03-11T06:20:46.877 回答
0

我对 Weblogic Portal 也有类似的问题。在这种情况下只需使用非泛型类型。

于 2010-03-11T06:27:03.197 回答