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);
}