Java 如何创建已知类型的类文本:class

Java 如何创建已知类型的类文本:class,java,generics,jls,Java,Generics,Jls,采取以下行动: public Class<List<String>> getObjectType() { // what can I return here? } 我可以从这个方法返回什么样的类文本表达式来满足泛型和编译?List.class不会编译,List.class也不会编译 如果您想知道为什么,我正在编写Spring的FactoryBean的实现,它要求我实现类getObjectType。然而,这不是一个春季问题 编辑:SpringSource的权威们听

采取以下行动:

public Class<List<String>> getObjectType() {
    // what can I return here?
}
我可以从这个方法返回什么样的类文本表达式来满足泛型和编译?List.class不会编译,List.class也不会编译

如果您想知道为什么,我正在编写Spring的FactoryBean的实现,它要求我实现类getObjectType。然而,这不是一个春季问题

编辑:SpringSource的权威们听到了我的哀号,因此Spring3.0.1将把getObjectType的返回类型更改为Class,这很好地避免了这个问题。

可以在springframework.org上找到,这提供了一些见解

例如


我不确定这是否可行,因为任何类文本都将被编译到class.forName。。。由于这是在运行时发生的,所以没有通用信息了。

您可以随时根据需要进行转换,如下所示

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

但我想那不是你想要的。嗯,它是有效的,有一个警告,但它并不完全漂亮

我刚找到这个

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

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


因此,选角可能是唯一的选择。

请查看SUN论坛上的讨论:

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


您不应该使用construct类。这是毫无意义的,应该在Java中产生一个警告,但事实并非如此。类实例总是表示原始类型,所以您可以拥有类;就这样。如果您想要一些东西来表示一个具体化的泛型类型,比如List,那么您需要一个超级类型标记,比如Guice使用的:

类的存在本身就是危险的。原因如下:

// 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);
}
那么这个呢:

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>

以下方法存在问题:

> public Class<List<String>> getModelType() {
>   return (Class<List<String>>) new ArrayList<String>().getClass();
> }
e、 如果你想测试一个对象是否为

org.eclipse.emf.common.util.BasicEList<String> 
是一种

List<String> 
基于上述getModelType方法的结果,例如:

BasicEList<String> fromObject = ...;
if (getModelType().isAssignableFrom(fromObject.getClass())) {
    transferFromModelToUi(getModelType().cast(fromObject));
}
它将导致false,而应该是true,因为这两个对象都实现了接口列表,因为getModelType返回的是List而不是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];
}

您可以这样实现该方法:

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

@Bozho:springframework链接有一个不同的方法签名java.lang.Class你在哪里找到了那句话?你的第一个例子对我的SE 1.6不起作用,只有第二个例子起作用。不过,将ArrayList实例化为变量并返回myVar.getClass是可行的。发现:java.lang.Class required:java.lang.ClassI同意这不是一个好主意,但java允许这样做,如果您试图实现一个接口,您可能没有选择,因此我们仍然需要一种半优雅的方式。这是一个奇怪的例子。由于泛型在运行时没有具体化,所以在许多情况下,运行时转换会绕过泛型类型系统。泛型主要是一种编译时构造,它允许您从类类型进一步约束类型。如果您可以保留泛型签名,这将非常有用,因为只要您不强制转换,将使许多代码更具可读性和类型安全性。我喜欢这种方式,因为您不需要创建新实例。外部强制转换是不必要的。您可以这样编写:return ClassList.class;,我觉得读起来更容易。
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];
}
public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}