将通用列表转换为非通用列表有何含义?

发布于 2024-08-24 12:37:54 字数 539 浏览 16 评论 0 原文

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

该类的一种用法是将容器的列表放入请求范围,由于 Websphere 的限制,我无法将通用 List 传递到请求范围(Websphere 不处理开箱即用的泛型)

如果我继续重构,我需要将 List 转换/转换为非泛型 List 对象..

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

颠倒这样的泛化会产生什么影响?我应该避免进行这种操纵吗?

编辑:代码片段很冗长,无法明确演示我所描述的内容。

I'm refatoring a home-grown DAO container, hoping to make the class generic. It internally uses an ArrayList to store the retrieved objects.

One usage of this class puts the container's list into a request scope, and due to a limitation of Websphere, I can't pass the generic List<Foo> to the request scope (Websphere doesn't handle generics out-of-the-box)

If I go ahead with my refactorings, I will need to convert/cast the List<Foo> into a non-generic List object..

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

What are the implications of reversing a generification like this? Should I avoid doing this kind of manipulation?

EDIT: The code snippet is verbose to explicitly demonstrate what I'm describing..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

朮生 2024-08-31 12:37:54

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

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

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

但是,我认为您可以编写

request.setAttribute("listThings", listFoo);

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

If the component type of the List does match the expected type, there is no problem.

Generics in Java are only used for type-checks by the compiler, they have not effect at runtime. If you are using an older library that does not support generics, you have no choice but to ignore the generic type.
Things should continue to work, as this system has been designed with backwards compatibility in mind.

So all you are losing is the compile-time type checking (it puts you back to where Java was at 1.4, which means, if the types match, everything will work, if not, you'll get ClassCastExceptions or other unwanted behaviour at runtime).

However, I think you can just write

request.setAttribute("listThings", listFoo);

This method takes any kind of Object. Even if it wanted a List, you could still pass a List<Foo> (which is still a List).

行雁书 2024-08-31 12:37:54

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

每当您处理 List< /code> 只是一个列表,您不会得到编译器检查以确保您没有将 Bla 放入列表中。因此,如果您调用 List.get() 并且它原来是隐藏在列表中的 Bla,您可能会得到 ClassCastException。但这只有在您通过某些代码将 Bla 放入列表中时才会发生。

如果您不想谨慎行事,那么如果您将 List 作为列表传递给任何可能向列表中添加非 Foo 的对象,请勿将其视为 List 每当您访问它时,但将其视为对象列表并添加instanceof检查。

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

Java uses "type erasure" for generics -- essentially that means that the compiler checks the generics, but the runtime forgets all about it and just treats it as a list of objects.*

Whenever you treat a List<Foo> as just a List, you won't get compiler checks to make sure you don't put a Bla into your list. So you could get a ClassCastException if you call List<Foo>.get() and it turns out to be a Bla hiding in the list. But that can only happen if you some code puts a Bla in your list.

If you wan't to be cautious, then if you pass the List<Foo> as a List to anything that might add a non-Foo to the list, don't treat it as a List<Foo> whenever you access it, but treat it as a list of Objects and add instanceof checks.

*Some of the information is accessible at runtime, but let's not complicate matters.

白衬杉格子梦 2024-08-31 12:37:54

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

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

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

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

如果 Foo 本身是泛型类型,事情会变得更加复杂。运行时检查仅对具体化类型(即:删除了泛型类型参数的类型)进行,因此如果您给它们一个 List> 并且它们插入一个 Set ; 或者只是一个 Set,您不会知道,因为无论哪种方式,元素的运行时/具体化类型都是 Set

A "non-generic" version of a generic type is called a "raw type".

Passing a generic type where the raw equivalent is requested is generally ok. This is actually the main reason generics in Java work the way they do (with erasure): to enable interoperability between "generified" code and pre-generics code.

The main thing you need to be careful about is that if you pass a List<Foo> to something that askes for a List, they may put non-Foo objects into the List. You won't get any compile time checking to help you here. You do get some runtime checks: a ClassCastException will be thrown when you use a method that returns a Foo on your List<Foo> and it has to return a non-Foo.

If you want more fail-fast behavior you can wrap your List<Foo> with Collections.checkedList() to get a List that'll check the type of elements on insertion.

Things get more complicated if Foo itself is a generic type. Runtime checks are only done on reified types (ie: the type with generic type parameters removed) so if you give them a List<Set<Bar>> and they insert a Set<Baz> or just a Set, you won't know since the runtime/reified type of the element is Set either way.

内心荒芜 2024-08-31 12:37:54

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

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

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

First, you can't cast a generic to a non-generic list so yeah you'd have to convert it.

Second, the two main advantages to a generic list are 1) it ensures that all objects are of the specified type and 2) it allows you to directly access methods of the object collection without needing to recast them. This allows you to write cleaner code and saves some processing cycles from having to cast back and fourth.

Neither one of these advantages is a dire need however. If you can't use them you won't notice a difference in performance. Your code may look a little messier though.

花心好男孩 2024-08-31 12:37:54

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

I have similar problems with Weblogic Portal. Just use none-generic type for this case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文