67

采取以下措施:

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

我可以从这个方法返回什么类文字表达式来满足泛型并编译?List.class不会编译,也不会List.<String>class

如果您想知道“为什么”,我正在编写 Spring 的实现FactoryBean<List<String>>,这需要我实现Class<List<String>> getObjectType(). 但是,这不是Spring 的问题。

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

4

9 回答 9

56

你总是可以投射到你需要的东西,就像这样

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

或者

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

但我认为这不是你所追求的。好吧,它有效,但有警告,但它并不完全是“美丽的”。

我刚发现这个

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

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

所以铸造可能是唯一的出路。

于 2010-01-06T11:13:15.613 回答
15

您永远不应该使用该构造Class<List<String>>。这是荒谬的,应该在 Java 中产生警告(但不会)。类实例总是代表原始类型,所以你可以拥有Class<List>; 而已。如果你想要一些东西来代表一个具体的泛型类型List<String>,你需要一个像 Guice 使用的“超级类型标记”:

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

于 2010-01-06T18:30:42.343 回答
12

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

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}
于 2014-04-13T16:15:40.667 回答
8

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

// 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);
}
于 2010-02-12T00:12:25.000 回答
6

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

例如

List<String> myList = new ArrayList<String>();
return (Class<List<String>>)myList.getClass();
于 2010-01-06T11:06:31.447 回答
2

查看 SUN 论坛上的讨论:

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

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

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

于 2010-01-06T11:21:55.387 回答
1

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

于 2010-01-06T11:08:36.573 回答
0

以下方法是有问题的:

> 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];
}
于 2014-03-28T07:54:20.497 回答
0

那这个呢:

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>
于 2013-05-09T09:11:52.853 回答