如何创建已知类型的类文字:Class>

发布于 2024-08-16 13:31:11 字数 584 浏览 5 评论 0 原文

考虑以下内容:

public Class<List<String>> getObjectType() {
    // what can I return here?
}

我可以从此方法返回什么类文字表达式来满足泛型并进行编译? List.class 不会编译,List.class 也不会编译。

如果您想知道“为什么”,我正在编写 Spring 的 FactoryBean> 的实现,它要求我实现 Class> getObjectType()。然而,这不是 Spring 问题。

编辑: SpringSource 的掌权者已经听到了我的哀声,因此 Spring 3.0.1 将把 getObjectType() 的返回类型更改为 Class,巧妙地避免了这个问题。

Take the following:

public Class<List<String>> getObjectType() {
    // what can I return here?
}

What class literal expression can I return from this method which will satisfy the generics and compile? List.class won't compile, and neither will List.<String>class.

If you're wondering "why", I'm writing an implementation of Spring's FactoryBean<List<String>>, which requires me to implement Class<List<String>> getObjectType(). However, this is not a Spring question.

edit: My plaintive cries have been heard by the powers that be at SpringSource, and so Spring 3.0.1 will have the return type of getObjectType() changed to Class<?>, which neatly avoids the problem.

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

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

发布评论

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

评论(9

杀手六號 2024-08-23 13:31:11

你总是可以投射到你需要的东西,比如

return (Class<List<String>>) new ArrayList<String>().getClass();

return (Class<List<String>>) Collections.<String>emptyList().getClass();

但我认为这不是你想要的。嗯,它可以工作,但有一个警告,但它并不完全“漂亮”。

我刚刚发现这个

为什么通配符参数化类型没有类文字?

因为通配符参数化类型没有精确的运行时类型表示。

所以选角可能是唯一的出路。

You can always cast to what you need, like

return (Class<List<String>>) new ArrayList<String>().getClass();

or

return (Class<List<String>>) Collections.<String>emptyList().getClass();

But I assume that's not what you are after. Well, it works, with a warning, but it isn't exactly "beautiful".

I just found this:

Why is there no class literal for wildcard parameterized types?

Because a wildcard parameterized type has no exact runtime type representation.

So casting might be the only way to go.

花开半夏魅人心 2024-08-23 13:31:11

您永远不应该使用构造 Class>。这是无意义的,并且应该在 Java 中产生警告(但没有)。类实例始终代表原始类型,因此您可以使用 Class;就是这样。如果您想要某种东西来表示像 List 这样的具体化泛型类型,您需要一个像 Guice 使用的“超级类型标记”:

http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html

You should never use the construct Class<List<String>>. It is nonsensical, and should produce a warning in Java (but doesn't). Class instances always represent raw types, so you can have Class<List>; that's it. If you want something to represent a reified generic type like List<String>, you need a "super type token" like Guice uses:

http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html

ペ泪落弦音 2024-08-23 13:31:11

您可以像这样实现该方法:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}

You can implement that method like this:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}
悲欢浪云 2024-08-23 13:31:11

Class> 的存在本质上是危险的。原因如下:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}

The existence of a Class<List<String>> is inherently dangerous. here's why:

// This statement generates a warning - for a reason...
Class<List<String>> unsafeListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> integerList = new ArrayList<Integer>(); // Ok
integerList.add(42); // Ok

System.out.println(unsafeListClass.isInstance(integerList)); // Prints "true".
List<String> stringList =
   unsafeListClass.cast(integerList); // Succeeds, with no warning!
stringList.add("Hello, World!"); // Also succeeds with no warning

for (int x: integerList) {
    // Compiles without warning, but throws ClassCastException at runtime
    System.out.println(100-x);
}
情感失落者 2024-08-23 13:31:11

在 springframework.org 上找到此链接,它提供了一些见解。

例如

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();

Found this link on springframework.org which gives some insight.

E.g.

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
妳是的陽光 2024-08-23 13:31:11

查看 SUN 论坛上的讨论:

http://forums.sun.com/thread .jspa?threadID=5253007

以及引用的博客文章,描述了使用“超级类型令牌”的解决方法:

http://gafter.blogspot.com/2006/12/super-type-tokens.html

Check out this discussion on the SUN forums:

http://forums.sun.com/thread.jspa?threadID=5253007

And the referenced blog post that describes a work around by using "super type tokens":

http://gafter.blogspot.com/2006/12/super-type-tokens.html

爱给你人给你 2024-08-23 13:31:11

我不确定这是否可能,因为任何类文字都将被编译为 Class.forName(...) 并且由于这种情况发生在运行时,因此没有留下通用信息。

I'm not sure if this is possible at all, since any class literal will be compiled to Class.forName(...) and since this happens at runtime there is no generic information left.

迷你仙 2024-08-23 13:31:11

这个怎么样:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

这个打印:

type = java.util.List<java.lang.Integer>

What about this:

public class TestMain {
    public static void main(String[] args) throws Exception {
        Type type = TestMain.class.getMethod("dummy").getGenericReturnType();
        System.out.println("type = " + type);
    }

    public List<Integer> dummy() {return null;}
}

This prints:

type = java.util.List<java.lang.Integer>
小…楫夜泊 2024-08-23 13:31:11

以下方法是有问题的:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

例如,如果您想测试类型的对象是否

org.eclipse.emf.common.util.BasicEList<String> 

类型

List<String> 

是基于上述 getModelType() 方法的结果的

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

,例如:它将导致 false,而它应该为 true,因为两个对象都实现接口 List(因为 getModelType() 返回 List 类型的 Class 对象,而不是 ArrayList)。

这是一种对我有用的方法(有点麻烦,但在上面的示例中会产生正确的结果,可以移动到静态初始化程序):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}

The following approach is problematic:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }

e.g. if you want to test whether an object say of type

org.eclipse.emf.common.util.BasicEList<String> 

is of type

List<String> 

based on the result of the aforementioned getModelType() approach, for example:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}

it will result in false whereas it should be true because both objects implement the interface List (since getModelType() returns a Class object of type List and not ArrayList).

Here is an approach that worked for me (a bit cumbersome but leads to correct results in the example above, could be moved to a static initializer):

public Class<List<String>> getModelType() {
    Class<?> arrayListClass = new ArrayList<String>().getClass();
    Class<?>[] interfaces = arrayListClass.getInterfaces();
    int index = 0;
    for (int i = 0; i < interfaces.length; i++) {
        if (interfaces[i].equals(List.class)) {
            index = i;
            break;
        }
    }
    return (Class<List<String>>) interfaces[index];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文