Java 如何创建已知类型的类文字:class<;列表<;字符串>&燃气轮机;

Java 如何创建已知类型的类文字:class<;列表<;字符串>&燃气轮机;,java,generics,jls,Java,Generics,Jls,采取以下行动: public Class<List<String>> getObjectType() { // what can I return here? } 公共类getObjectType(){ //我能在这里还什么? } 我可以从这个方法返回什么样的类文本表达式来满足泛型和编译List.class不会编译,List.class也不会编译 如果您想知道“为什么”,我正在编写Spring的FactoryBean的实现,它要求我实现类getObjectTy

采取以下行动:

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

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

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

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

例如

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

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

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

return (Class<List<String>>) new ArrayList<String>().getClass();
返回(类)新的ArrayList().getClass();

return(Class)Collections.emptyList().getClass();
但我想那不是你想要的。嗯,它是有效的,有一个警告,但它并不完全是“美丽的”

我刚找到这个

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

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


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

请查看SUN论坛上的讨论:

以及引用的博客文章,该文章描述了通过使用“超级类型令牌”来解决的问题:


您不应该使用构造
。这是毫无意义的,应该会在Java中产生警告(但不会)。类实例始终表示原始类型,因此您可以使用
Class
;就这样。如果您想要一些东西来表示一个具体化的泛型类型,如
列表
,您需要一个“超级类型标记”,如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);
}
//此语句生成警告-原因是。。。
Class unsalistclass=(Class)(Class)List.Class;
List integerList=new ArrayList();//好啊
整数列表。添加(42);//好啊
System.out.println(unsafeListClass.isInstance(integerList));//打印“真”。
列表字符串列表=
unsafeListClass.cast(整数列表);//成功,没有任何警告!
stringList.add(“你好,世界!”);//也会在没有警告的情况下成功
for(整数x:整数列表){
//编译时没有警告,但在运行时抛出ClassCastException
系统输出打印Ln(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;}
}
公共类TestMain{
公共静态void main(字符串[]args)引发异常{
Type Type=TestMain.class.getMethod(“dummy”).getGenericReturnType();
System.out.println(“type=“+type”);
}
public List dummy(){return null;}
}
这张照片是:

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

以下方法存在问题:

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

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

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

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

下面是一种对我有效的方法(有点麻烦,但在上面的示例中可以得到正确的结果,可以移动到静态初始值设定项):

公共类getModelType(){
类arrayListClass=新的ArrayList().getClass();
类[]接口=arrayListClass.getInterfaces();
int指数=0;
for(int i=0;i
您可以这样实现该方法:

public Class<List<String>> getObjectType() {
    return (Class<List<String>>) ((Class)List.class);
}
公共类getObjectType(){
返回(类)((类)列表.Class);
}

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