2010-02-10 52 views
4

Java泛型和考虑下面的代码类型擦除

public void example(Object o) { 
    if(o instanceof List<MyType>) 
    //do something 
} 

我明白,这是不可能的(和为什么它是不可能的)给定的Java泛型处理和类型擦除方式。

我的问题是,什么是最好/最干净的方式来实现这一目标?或者我唯一能做的就是检查o是否为List<?>

+0

这个问题听起来很熟悉,好像人被要求在过去90天左右。尝试查看[http://stackoverflow.com/questions/1004022/java-generic-class-determine-type]。 – 2010-02-10 03:19:50

回答

-3

也许通过检查在运行时的对象类型,也许是这样的:

if (o.getClass() == List.class) ... 

很明显,你必须深入挖掘对象的类类型,看它是否是一个精确匹配List<>和列表的元素类型。

+0

在运行时,列表的类与列表完全相同 – 2010-02-10 03:09:58

+1

看起来'List'是一个接口,这可能是一个坏主意 – 2010-02-10 03:13:51

0

短检查类型列表中所有的项目,它是无法确定Java中的泛型参数的类型,因为这只是存在在编译时和运行时之前被移除。

我的建议是,除非你绝对需要让方法接受一个对象(例如符合接口规范或覆盖Object.equals),以便将所需的正确类型作为该方法的参数,并且用可能需要运行该方法的各种其他类型重载该方法。

2

您不能检查超过o instanceof List<?>

您从Java泛型中获得的类型安全性仅在编译时发生。 像你这样的方法(它接受一个对象,然后试图弄清楚该怎么做),在这个设计中效果并不好。 我明白为什么这样一个动态的方法是必要的一段时间,但考虑版本补充它输入参数:

public void example(Object o) { 
    if(o instanceof List<?>) 
    example((List)o); // can only hope that the type is correct here 
} 

public void example(List<MyType> list){ 
    // do something 
} 

在那些可以使用的情况下,你获得仿制药的全部好处。在其他情况下,你必须依靠阅读你的Javadoc的人,并只传递正确的类型。

什么甚至以上方法不能做的是有List<TypeA>List<TypeB>两个不同的代码路径。如果这对你来说真的需要,可以考虑使用自己的包装类型ListOfTypeA,ListOfTypeB

取决于你需要做什么,甚至有可能不会有必要看看删除类型列表中作为一个整体,只是在运行时类型的各个元件的工作:

for (Object o: list){ 
    if (o instanceof TypeA){ 
    } 
    if (o instanceof TypeB){ 
    } 
} 
0

Java在编译后会擦除泛型的类型信息,所以您不能以这种方式动态地检查类型参数。

如果这个代码的所有路径限制类型参数,然后做:

// Return true if object is a list of MyType, false if it is not a list, or is 
// empty 
boolean isListOfMyType(Object o) { 
    if (o instanceof List) { 
     List<?> l = (List<?) o; 
     return (l.size() > 0 && (l.get(0) instanceof MyType) 
    } 
    return true; 
} 

是类型安全的,但如果该列表不为空时才会有效。如果不是,您需要修改上述内容以检查所有项目是否通过了instanceof测试(或者如果您允许列表中有空值,则它们为空)。

另一种替代方法是创建一个子类,该子类扩展为ArrayList<MyType>并使用 这表示您的instanceof检查。

最后但并非最不重要的一个实现List<MyType>的子类将允许您使用Class.getGenericInterfaces()方法获取类型参数。有关详细信息,请参见this

对于上述两种方法中的任何一种,您必须确保创建列表总是实例化这些类型之一。 IE浏览器。如果调用者去构建他们自己的ArrayList<MyType>,它将无法工作。