Проверить, является ли объект экземпляром типа параметра


86

Есть ли способ определить, является ли объект экземпляром универсального типа?

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

Это явно не работает. Есть ли альтернатива? Например, я хочу использовать отражение Java для создания экземпляра класса, а затем проверить, имеет ли он тип generic T.

Ответы:


128

Единственный способ выполнить эту проверку - иметь Classобъект, представляющий тип:

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

Если вы не хотите получать typeв качестве параметра метода, возможно, вы хотите его инициализировать:Class type = ((T) new Object()).getClass();
JordiVilaplana

9
@JordiVilaplana Это неверно, он предоставит вам java.lang.Object в качестве класса. Проверьте это: ideone.com/bxt9Jq
Шри Харша Чилакапати

3
Использование:Class<T> type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Ton Snoei

22

Чтобы расширить пример Марка Петерса, часто вам нужно сделать что-то вроде:

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

11

Если вы не хотите передавать тип класса в качестве параметра, как упомянул Марк Петерс, вы можете использовать следующий код. Престижность Дэвида О'Мира.

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

5
Это даетType safety: Unchecked cast from Type to Class<T>
Марко Сулла

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
Это не работает! Приведение удачно для всех типов. Вот почему он выдает предупреждение компиляции "Unchecked cast".
Lii

3

Было бы разумнее наложить ограничение на то, где тип Tиспользуется для параметризации Classтипа. Когда вы передаете тип, вместо того, чтобы использовать что-то вроде Class<?>, вы должны использовать Class<? extends T>.


1
Если вы хотите знать точный тип T во время выполнения, важно потребовать, чтобы вызывающий объект передавал Class <T>, а не Class <? расширяет T>. Например, код Puce не будет компилироваться с Class <? расширяет T>.
Теодор Мердок

1

Это будет работать (частично), только если у вас есть объект типа T. Затем вы можете получить класс этого объекта, посмотреть java.lang.Class<T>и выяснить, совпадает ли он с рассматриваемым объектом.

Но обратите внимание, что это противоречит самой причине, по которой у нас есть родословные: использование универсального типа - это способ сказать, что вам все равно, какой он на самом деле тип (вплоть до верхней и нижней границ, которые могут быть указаны).


Класс <?>, Возвращаемый из вызова .getClass () для ненулевого экземпляра T, не обязательно является Class <T>. Лучшее, что вы можете гарантировать, это то, что это Class <? расширяет T>.
Теодор Мердок
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.