[英]Creating parameterized type object using anonymous class
This might be a stupid question, but I just saw a question asking how to create a Type variable for a generic type .这可能是一个愚蠢的问题,但我刚刚看到一个问题,询问如何为泛型 type 创建一个 Type 变量。 The consensus seemed to be that you should have a dummy method returning that type, and then use reflection to get it (in this case he wanted
Map<String, String>
).共识似乎是你应该有一个返回该类型的虚拟方法,然后使用反射来获取它(在这种情况下他想要
Map<String, String>
)。 Something like this :像这样的事情:
public Map<String, String> dummy() { throw new Error(); }
Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType();
My question is, not having used reflection that much, couldn't you just do something like:我的问题是,没有那么多使用反射,你不能做这样的事情:
Type mapStringString = new ParameterizedType() {
public Type getRawType() {
return Map.class;
}
public Type getOwnerType() {
return null;
}
public Type[] getActualTypeArguments() {
return new Type[] { String.class, String.class };
}
};
Would this work?这行得通吗? If not, why not?
如果没有,为什么不呢? And what are some of the dangers/problems if it does (besides being able to return some Type like
Integer<String>
which is obviously not possible.如果确实如此,会有哪些危险/问题(除了能够返回某些类型,如
Integer<String>
这显然是不可能的。
Sure you could, and for most applications it would probably be sufficient.当然可以,而且对于大多数应用程序来说,这可能就足够了。
However, using the first method, you get a more refined object.但是,使用第一种方法,您可以获得更精致的对象。 Let's say for instance that you create an object
type1
using the first method, and type2
using the second method.例如,假设您使用第一种方法创建对象
type1
,使用第二种方法创建对象type2
。 Then type1.equals(type2)
would return true (since the first method returns an object that properly implements the equals-method) but type2.equals(type1)
would return false (since in the second method, you haven't overridden the equals-method, and are using the implementation from Object
).然后
type1.equals(type2)
将返回 true(因为第一个方法返回一个正确实现 equals 方法的对象)但type2.equals(type1)
将返回 false(因为在第二个方法中,您没有覆盖 equals -method,并且正在使用Object
的实现)。
Same reasoning applies to other (sometimes useful methods) such as toString
, hashCode
etc. The second method does not provide useful implementations of these.同样的推理适用于其他(有时有用的方法),例如
toString
、 hashCode
等。第二种方法不提供这些的有用实现。
If you include Google's Guava library in your project (you should; it's great), use its TypeToken
to get a type.如果您的项目中包含 Google 的Guava库(您应该这样做;它很棒),请使用它的
TypeToken
来获取类型。 Google's Gson library (for interacting with JSON) has a similar version . Google 的Gson库(用于与 JSON 交互)有一个类似的版本。 Both are used like this (to get a
Type
representing List<String>
:两者都像这样使用(获取表示
List<String>
的Type
:
Type t = new TypeToken<List<String>>(){}.getType();
If you don't want to rely on any third-party libraries, you can still use anonymous types to get a generic concrete type with one line of code (this technique will not work with interfaces and could be more trouble than it's worth for Abstract Types).如果您不想依赖任何第三方库,您仍然可以使用匿名类型通过一行代码获得通用的具体类型(这种技术不适用于接口,并且可能比 Abstract 的价值更麻烦类型)。 To get a
Type
representing HashMap<String, String>
, do this:要获取表示
HashMap<String, String>
的Type
,请执行以下操作:
Type t = new HashMap<String, String>(){}.getClass().getGenericSuperclass();
I have verified that resulting Type
instance .equals()
the Type
instances created by Gson 's TypeToken
, though have not verified the same for Guava 's version of TypeToken
, which I do not have access to at the moment.我已经验证生成的
Type
实例.equals()
是由Gson的TypeToken
创建的Type
实例,但尚未验证Guava版本的TypeToken
,我目前无法访问。 (Guava is a more general-purpose library that is so handy for all sorts of things, you should probably be using it anyways.) (Guava 是一个更通用的库,它对各种事情都非常方便,无论如何你都应该使用它。)
Actually, I think the simplest way (== least code) to do this would be a dummy interface extending the type your interested in, and then getGenericInterfaces()[0]
from its class (use getGenericSuperclass()
if you're interested in a class):实际上,我认为最简单的方法(==最少代码)是一个扩展您感兴趣的类型的虚拟接口,然后从它的类中获取
getGenericInterfaces()[0]
getGenericSuperclass()
如果您感兴趣,请使用getGenericSuperclass()
一类):
private interface MapStringString extends Map<String, String> {}
private static ParameterizedType mapStringString(){
return (ParameterizedType) MapStringString.class.getGenericInterfaces()[0];
}
It doen't scale well, though, as you have to create a new class for every ParameterizedType
you want to represent.但是,它不能很好地扩展,因为您必须为要表示的每个
ParameterizedType
创建一个新类。 I don't see why your implementation wouldn't do (unless there are narrowing casts somewhere), and it does have the appealing benefit that you can make it reusable.我不明白为什么你的实现不会做(除非在某处有缩小强制转换),而且它确实有一个吸引人的好处,你可以使它可重用。
In addition to the mentioned libs from Google there is also a lib from Apache that does the job.除了上面提到的来自 Google 的库之外,还有一个来自 Apache 的库可以完成这项工作。
import org.apache.commons.lang3.reflect.TypeUtils;
...
ParameterizedType type = TypeUtils.parameterize(List.class, Double.class);
...
Finde code on GitHub here and Maven artifacts here .在GitHub上FINDE代码在这里和Maven的文物在这里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.