Java 如何创建已知类型的类文字:Class<List<String>>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2012306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a class literal of a known type: Class<List<String>>
提问by skaffman
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
.
我可以从这个方法返回什么类文字表达式来满足泛型并编译?List.class
不会编译,也不会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 nota Spring question.
如果您想知道“为什么”,我正在编写 Spring 的实现FactoryBean<List<String>>
,这需要我实现Class<List<String>> getObjectType()
. 但是,这不是Spring 问题。
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.
编辑:SpringSource 的权力已经听到了我的悲痛呼喊,因此 Spring 3.0.1 将返回类型getObjectType()
更改为Class<?>
,这巧妙地避免了这个问题。
采纳答案by Bozho
You can always cast to what you need, like this
你总是可以投射到你需要的,像这样
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.
因此,铸造可能是唯一的出路。
回答by JRL
回答by perdian
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.
我不确定这是否可能,因为任何类文字都将被编译为,Class.forName(...)
并且由于这是在运行时发生的,因此没有留下通用信息。
回答by Mike Tunnicliffe
Check out this discussion on the SUN forums:
在 SUN 论坛上查看此讨论:
http://forums.sun.com/thread.jspa?threadID=5253007
http://forums.sun.com/thread.jspa?threadID=5253007
And the referenced blog post that describes a work around by using "super type tokens":
引用的博客文章描述了使用“超级类型令牌”的解决方法:
回答by Kevin Bourrillion
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:
你永远不应该使用构造Class<List<String>>
。这是荒谬的,应该在 Java 中产生警告(但不会)。类实例始终表示原始类型,因此您可以拥有Class<List>
; 就是这样。如果你想要一些东西来代表一个具体的泛型类型,比如List<String>
,你需要一个像 Guice 使用的“超级类型标记”:
http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html
http://google-guice.googlecode.com/git/javadoc/com/google/inject/TypeLiteral.html
回答by finnw
The existence of a Class<List<String>>
is inherently dangerous. here's why:
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);
}
回答by mazi
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>
回答by Lukas Z.
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:
基于上述 getModelType() 方法的结果,例如:
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).
它将导致 false 而它应该是 true 因为这两个对象都实现了接口 List (因为 getModelType() 返回类型为 List 而不是 ArrayList 的 Class 对象)。
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];
}
回答by Saeed Zarinfam
You can implement that method like this:
您可以像这样实现该方法:
public Class<List<String>> getObjectType() {
return (Class<List<String>>) ((Class)List.class);
}