我可以获取泛型类型的Clazz.class吗?

3

我正在试图在 List<MyType> 上调用 EasyMock.isA(Class<T>)。有没有一种方法可以不出现警告的情况下完成它?

我尝试了以下方法:

isA(List<MyType>.class);  // doesn't compile
isA(List.<MyType>class);  // syntax error on tokens (MyType), misplaced construct
isA(List.class);          // This gives a warning: Type safety: The expression of type List needs unchecked conversion to conform to List<MyType>

编辑:

Jakub HR给出了正确的答案。然而,对于我的特定情况,我需要这个功能用于EasyMock,我可以简单地使用

EasyMock.<List<MyType>>anyObject()

1
由于JVM中的类型参数擦除,您无法检查它(除非您使用自定义泛型列表类,该类还将内部存储相应类型的实际Class <?>对象(必须手动提供))。 - Display Name
4个回答

4

根据《Effective Java》:

在新代码中不应使用原始类型的规则有两个次要例外,这两个例外源于泛型类型信息在运行时被擦除的事实。必须在类文字中使用原始类型。规范不允许使用参数化类型(尽管允许数组类型和基本类型)。换句话说,List.classString[].classint.class 都是合法的,但是 List<String>.classList<?>.class 不是���


0
由于JVM中的类型参数擦除,您无法检查它(除非您使用自定义泛型List类,该类还将相应类型的Class<?>对象存储在内部(必须手动提供))。
这是因为在运行时无法知道泛型类型参数 - List<String>List<MyType>等都会在运行时“被擦除”为List<Object>(或只是List - 没有区别)。也许您还想阅读一个更深入的例子

你错了。List<String> 被更改为 List 而不是 List<Object>。 - Jakub H
@JakubHr 这是一样的。 List 只是一个“原始类型”,它在语言层面上有所不同,但在字节码中没有区别。 - Display Name

0

建议/接受的答案并不是完全正确的。这里是一个更完整的答案:

myMock.myMeth(isA(List.class)); // #1 如果arg == null,则失败,警告 myMock.myMeth(EasyMock.<List<MT>> anyObject()); // #2 即使arg == null也会成功 myMock.myMeth(anyObject()) // #3 与#2相同

myMock.myMeth(EasyMock.<List<MT>> notNull()); // #4 与#1相同,没有警告! myMock.myMeth(notNull()); // #5 可能与#1相同,信息较少

因此,如果您真的想要与isA()相同的行为,请使用notNull()而不是anyObject()。请注意,当使用任何对象(anyObject())或非空对象(notNull())时,您实际上依赖于编译器已确保调用的代码确实传递了正确的列表。如果您以某种方式将其他对象“伪造”到调用中(几乎不可能),EasyMock将无法使用任何对象(anyObject())或非空对象(notNull())来捕获它。


0

您可以按照以下方式获取它:

Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

我在调用 getClass() 的对象是什么?this?那似乎不对。 - Zoltán
getClass() 指的是 new ArrayList<MyType>() {}.getClass(); 中的方法。虽然我从未尝试过,但理论上应该可以运行。 - Shishir Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接