众所周知,Java 集合的泛型E
或通配符?
是实例化特定集合中允许的内容/对象所必需的。
我的问题是我们可以从下面的代码中知道特定集合的通配符或对象吗?
Object inbound = java.io.ObjectInputStream().readObject();
if(inbound instanceof List<?>) {
// know `?.getClass()`
}
众所周知,Java 集合的泛型E
或通配符?
是实例化特定集合中允许的内容/对象所必需的。
我的问题是我们可以从下面的代码中知道特定集合的通配符或对象吗?
Object inbound = java.io.ObjectInputStream().readObject();
if(inbound instanceof List<?>) {
// know `?.getClass()`
}
不。由于类型擦除,在运行时没有办法区分List
s。
inbound
如果是在类型声明中定义其类型参数的类,则只能找到类型参数。例如,假设您序列化了一个NodeList
声明如下的实例:
final class NodeList extends ArrayList<Node> { }
然后当你反序列化它时,你可以这样做:
Object inbound = ois.readObject();
if (inbound instanceof List<?>) {
Type t = inbound.getClass().getGenericSuperclass();
if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) t;
for (Type p : pt.getActualTypeArguments()) {
if (p instanceof TypeVariable<?>)
System.out.println("Unknown");
else
System.out.println(p); /* Prints "interface Node" */
}
}
}
如果您确定列表至少包含一个元素,则可以,在这种情况下,您可以简单地调用getClass
它。
否则,这实际上是不可能的,尽管您可以将正确的 Class 对象与 List 一起序列化。
恕我直言,如果您需要这样做,最好的解决方案是使用 Guice:http ://blog.publicobject.com/2008/11/guice-punches-erasure-in-face.html 。
正如其他人所提到的,类型擦除是问题的根源。一个很好的解释是http://docs.oracle.com/javase/tutorial/java/generics/erasure.html。
您可以查看源代码ArrayList
并查看其工作原理的示例。ArrayList
持有一个(第Object[]
111 行)。它不知道对象的类型。您可以看到“类型安全”实际上只是通过强制转换实现的,例如第 371 行。