测试对象是否为参数类型的实例


82

有没有办法确定对象是否是泛型类型的实例?

public <T> test(Object obj) {
    if (obj instanceof T) {
        ...
    }
}

这显然行不通。有其他选择吗?就像我想使用Java反射来实例化一个类,然后检查以确保它是通用类型T

Answers:


125

进行此检查的唯一方法是,是否具有Class表示类型的对象:

Class<T> type; //maybe passed into the method
if ( type.isInstance(obj) ) {
   //...
}

如果不想type作为方法参数获取,则可能要对其进行初始化:Class type = ((T) new Object()).getClass();
JordiVilaplana 2016年

9
@JordiVilaplana这是不对的,它将为您提供java.lang.Object作为类。看看这个:ideone.com/bxt9Jq
Sri Harsha Chilakapati

3
使用:Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Ton Snoei

20

为了扩展Mark Peters的样本,通常您想做以下事情:

Class<T> type; //maybe passed to the method
if ( type.isInstance(obj) ) {
   T t = type.cast(obj);
   // ...
}

11

如果您不想像Mark Peters那样将Class类型作为参数传递,则可以使用以下代码。感谢David O'Meara。

  Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
                  .getActualTypeArguments()[0];
  if (type.isInstance(obj)) {
      ...
  }

5
它给了Type safety: Unchecked cast from Type to Class<T>
Marco Sulla

5

你可以试试看

// Cast your object to the generic type.
T data = null;
try {
    data = (T) obj;
} catch (ClassCastException cce) {
    // Log the error.
}

// Check if the cast completed successfully.
if(data != null) {
    // whatever....
}

7
这行不通!强制转换适用于所有类型。这就是为什么它会给出“未经检查的强制转换”编译警告的原因。

3

对类型T用于参数化Class类型的位置进行限制会更有意义。当您传入类型时Class<?>,您应该使用而不是使用类似的东西Class<? extends T>


1
如果您想在运行时知道T的确切类型,重要的是要求调用者传递Class <T>而不是Class <?扩展T>。例如,Puce的代码无法使用Class <?进行编译。扩展T>。
西奥多·默多克(

1

仅当您具有类型T的对象时,这才(部分)起作用。然后,您可以获取该对象的类,查看java.lang.Class<T>并查找它是否与所讨论的对象相同。

但是请注意,这与我们拥有泛型的原因恰恰相反:使用泛型类型是一种方式,您不必关心它实际上是什么类型(可以指定上限和下限)。


从非null T实例的.getClass()调用返回的Class <?>不能保证是Class <T>。您可以保证的最好是它是Class <?扩展T>。
西奥多·默多克(
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.