Class上未经检查的警告

发布于 2024-09-24 14:12:26 字数 524 浏览 10 评论 0原文

假设我有以下方法,可用于创建指定给定类型的集合。

private static Collection<?> void create(Class<? extends Collection<?>> cls) {
    return cls.newInstance();
}

如果在运行时传入 cls 参数,这一切都很好:

List<String> list = new LinkedList<String>();
create(list.getClass());

但是如何在代码中调用此方法而不出现未经检查的警告?假设我想做类似的事情:

create(LinkedList.class);

它会抱怨 create(Class) 未定义,严格来说这是正确的,因为 List 不是 Collection 的 #capture,但我该如何让它工作呢?

非常感谢!

Suppose I have the following method, which can be used to create a collection of a given type specified.

private static Collection<?> void create(Class<? extends Collection<?>> cls) {
    return cls.newInstance();
}

This is all good if the cls argument is passed in during runtime:

List<String> list = new LinkedList<String>();
create(list.getClass());

But how do I invoke this method in code without an unchecked warning? Say I want to do something like:

create(LinkedList.class);

It'll complain that create(Class) is not defined, which strictly speaking is correct because List is not #capture of Collection, but how do I make it work?

Many thanks!

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

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

发布评论

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

评论(2

日久见人心 2024-10-01 14:12:26

Neal Gafter 在此处讨论了这个问题。解决方法是使用超级类型标记。我相信,这就是 Guice 用来维护通用类型信息的方法。

基本上,它是一个额外的类,您可以使用它来表示类型,而不是使用 Foo.class。您可以这样使用它:

TypeReference<LinkedList<String>> x = new TypeReference<LinkedList<String>>() {};
create(x);

请注意,您尝试使用 raw 类型 LinkedList 仍然会导致编译器抱怨,并且是故意的 - 当您使用原始类型时,你基本上选择退出类型安全。但这种方案允许您以一种更困难的方式表达泛型类型。

Neal Gafter talks about pretty much exactly this problem here. The fix is to use super type tokens. This is what Guice uses to maintain generic type information, I believe.

Basically it's an extra class you can use to represent a type instead of using Foo.class. You'd use it like this:

TypeReference<LinkedList<String>> x = new TypeReference<LinkedList<String>>() {};
create(x);

Note that your attempt to use the raw type LinkedList would still cause the compiler to complain, and deliberately so - when you use raw types, you're basically opting out of type safety. But this scheme allows you to express the generic type in a way which is otherwise harder.

留一抹残留的笑 2024-10-01 14:12:26

我们这里有两种泛型类型,一种用于集合的子类型,一种用于集合的元素类型。以下代码可以工作:

private static <C extends Collection<E>, E>
C create(Class<C> cls) throws Exception
{
    return cls.newInstance();
}

使用示例。没有警告。

    Class<LinkedList<String>> clazz = ...;
    LinkedList<String> result = create(clazz);

现在的问题是我们如何获得clazz?你必须非常努力地说服编译器:

    List<String> list = new LinkedList<String>();
    clazz = (Class<LinkedList<String>>)list.getClass();

    clazz = (Class<LinkedList<String>>)(Class<?>)LinkedList.class;

我们可以有一个实用方法来简化类型转换:

public static <C extends Collection, E, T extends Collection<E>>
Class<T> type(Class<C> classC, Class<E> classE)
{
    return (Class<T>)classC;
}

//usage:
    clazz = type(LinkedList.class, String.class);
    result = create(clazz);

乐趣是递归的:

    Class<LinkedList<LinkedList<String>>> clazz2;
    LinkedList<LinkedList<String>> result2;

    clazz2 = type(LinkedList.class, clazz);
    result2 = create(clazz2);

但在某些时候,我们必须停止这个愚蠢的游戏。通用类型应该帮助我们,而不是折磨我们。当它变得太麻烦并且使我们的程序无法阅读时,就放弃它吧。使用我们已经快乐地生活了很多年的该死的原始类型。

we have two generic types here, one for subtype of collection, one for element type of collection. following code can work:

private static <C extends Collection<E>, E>
C create(Class<C> cls) throws Exception
{
    return cls.newInstance();
}

usage example. no warnings.

    Class<LinkedList<String>> clazz = ...;
    LinkedList<String> result = create(clazz);

the question now becomes how do we obtain clazz? You have to convince the compiler really hard:

    List<String> list = new LinkedList<String>();
    clazz = (Class<LinkedList<String>>)list.getClass();

    clazz = (Class<LinkedList<String>>)(Class<?>)LinkedList.class;

we can have a utility method to ease the type casting:

public static <C extends Collection, E, T extends Collection<E>>
Class<T> type(Class<C> classC, Class<E> classE)
{
    return (Class<T>)classC;
}

//usage:
    clazz = type(LinkedList.class, String.class);
    result = create(clazz);

The fun is recurive:

    Class<LinkedList<LinkedList<String>>> clazz2;
    LinkedList<LinkedList<String>> result2;

    clazz2 = type(LinkedList.class, clazz);
    result2 = create(clazz2);

But at some point, we have to stop this silly game. Generic typing is supposed to help us, not to torture us. When it becomes too cumbersome and makes our programs impossible to read, just drop it. Use the god damn raw types that we have lived with happily for years.

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