2010-03-11 98 views
1

我正在推崇一个本土的DAO容器,希望能够让这个类变得通用。它在内部使用ArrayList来存储检索到的对象。将泛型列表转换为非泛型列表有什么含义?

该类的一个用法是将容器的列表放入请求范围,并且由于Websphere的限制,我无法将通用List<Foo>传递到请求范围(Websphere无法处理超出范围的泛型-box)

如果我和我的重构先走,我将需要转换/施放List<Foo>到非通用List对象..

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

什么是扭转这样的generification的影响?我应该避免做这种操作吗?

编辑:的代码片断是详细明确地证明什么,我描述..

+0

您不需要将中间任务分配给listThings;您可以直接将listFoo设置为请求。 – 2010-03-11 06:44:45

回答

3

如果列表中的组件类型不匹配预期的类型,是没有问题的。

Java中的泛型只用于编译器的类型检查,它们在运行时不起作用。如果您使用的是不支持泛型的较旧的库,则别无选择,只能忽略泛型。 事情应该继续工作,因为这个系统的设计考虑了向后兼容性。因此,所有你正在失去的是编译时类型检查(它会让你回到Java处于1.4的地方,这意味着如果类型匹配,一切都会工作,否则,你将得到ClassCastExceptions或其他运行时不需要的行为)。

不过,我觉得你可以只写

request.setAttribute("listThings", listFoo); 

此方法需要任何类型的对象。即使它想要一个List,你仍然可以通过一个List<Foo>(这仍然是一个List)。

+0

很酷,只是想明确说明我在代码示例中描述的是什么 – brasskazoo 2010-03-11 06:21:55

+0

您可以将您的'List '传递给每个需要非通用列表的方法。 WebSphere不能干预这一点。这就是向后兼容性的工作原理。 – Thilo 2010-03-11 06:25:37

0

首先,你不能将泛型转换为非泛型列表,所以你必须转换它。

其次,通用列表的两个主要优点是1)它确保所有对象都是指定的类型; 2)它允许您直接访问对象集合的方法而不需要重新对其进行重新设置。这使您可以编写更清晰的代码,并节省一些处理周期,从而不必回头和后退。

然而,这些优点都不是最迫切的需求。如果你不能使用它们,你不会注意到性能的差异。尽管如此,你的代码可能看起来有点混乱。

+1

您绝对可以将泛型转换为非泛型列表。你可能不得不压制警告,但你绝对可以做到。这是有道理的,因为它们在擦除后是完全相同的类型。 – polygenelubricants 2010-03-11 06:22:14

+0

“你不能将泛型转换为非泛型列表”。你可以写'List x =(List)listFoo'。 – Thilo 2010-03-11 06:23:11

+0

啊我的不好。我一定会一直在想“你不能把一个通用列表放到另一个通用列表中”,并把它混淆在我的脑海中。 – 2010-03-11 06:26:08

2

Java使用“类型擦除”为仿制药 - 本质上意味着编译器检查的仿制药,但运行时忘记所有关于它,只是把它当作对象的列表*

每当你治疗List<Foo>只是一个List,你不会得到编译器检查,以确保你不会把Bla放到你的列表中。所以如果你打电话给List<Foo>.get(),你会得到一个ClassCastException,并且它变成了一个Bla隐藏在列表中。但是只有当你的代码在你的列表中放入一个Bla时才会发生这种情况。

如果你wan't谨慎,那么如果你通过List<Foo>作为一个列表来任何可能添加非富到列表中,不要把它当作一个List<Foo>每当你访问它,但治疗它作为Objects的列表并添加instanceof检查。

*部分信息可在运行时访问,但不要让事情复杂化。

+0

幸运的是,在这种情况下使用列表仅用于显示目的,所以没有爆炸的风险在我们的脸上 – brasskazoo 2010-03-11 06:31:59

0

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

1

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

在请求原始等价物时传递一般类型通常是可以的。这实际上是Java中泛型工作的主要原因(使用擦除):实现“基因化”代码和泛型前代码之间的互操作性。

你需要小心的是,如果你传递一个List<Foo>的东西,askes的List,他们可能把非Foo物体插入List最主要的。你不会得到任何编译时间检查来帮助你。您得到一些运行时检查:当您使用一种方法返回上的Foo并且必须返回非Foo时,将会抛出ClassCastException

如果你想要更快的失效行为,你可以用包装Collections.checkedList()来获得一个List来检查插入时元素的类型。

如果Foo本身是一个通用类型,情况会变得更加复杂。运行时检查仅在具体化类型上完成(即:删除了泛型类型参数的类型),所以如果您给它们一个List<Set<Bar>>并且它们插入Set<Baz>Set,那么您将不会知道,因为元素的运行时/具体化类型无论哪种方式都是Set