2016-01-05 3 views
0

Я хотел бы знать, если что-то подобное возможно в Java (сочетание C++ и Java вперед)Java общий тип сравнения

template<typename T> bool compare(Wrapper wrapper) { 
    if(wrapper.obj.getClass().equals(T.class)) 
     return true 
    return false 
} 

Чтобы уточнить, функция принимает объект, который содержит Java. lang.object, но я хотел бы быть в состоянии передать эту оболочку в этой общей функции сравнения, чтобы проверить, является ли этот объект определенного типа, т.е.

if(compare<String>(myWrapper)) 
    // do x 

ответ

2

нет, это не представляется возможным из-за erasure. В принципе, метод compare не имеет понятия, что такое T. Существует только один метод compare (в отличие от C++, где есть один за T), и ему не дана какая-либо информация о том, как он был вызван (то есть, что вызывающий вызывал его T).

Типичным решением является класс (или метод) принять Class<T> cls, а затем использовать cls.isInstance:

public <T> boolean compare(Wrapper wrapper, Class<T> cls) { 
    return cls.isInstance(wrapper.obj); 
} 

// and then, at the call site: 
if (compare(wrapper, Foo.class)) { 
    ... 
} 

Конечно, это означает, что сайт вызова должен иметь Class<T> объект. Если этот сайт вызова сам по себе является универсальным методом, ему необходимо получить эту ссылку от своего вызывающего абонента и так далее. В какой-то момент кто-то должен знать, что такое конкретный тип, и что кто-то проходит в Foo.class.

+0

Я вижу, это решение должно быть подходящим для того, что мне нужно, спасибо. Как этот метод обрабатывает наследование btw? т.е. если у меня есть B: A, будет сравнивать (B, A.class) возврат true? – Madden

1

Вы не можете ссылаться на статические элементы параметра типа (например, вы пытаетесь сделать это в форме T.class). Вы также не можете использовать их в выражениях instanceof. В более общем плане, поскольку Java-генерики реализуются с помощью стирания типа, вы не можете использовать параметры типа каким-либо образом во время выполнения - весь тип анализа выполняется статически во время компиляции.

В зависимости от того, что вы после этого, существует как минимум два альтернативных подхода.

Первый и более обычный, чтобы гарантировать, что необходимые типы могут быть проверены статически. Например, вы можете параметризовать свой класс Wrapper с типом объекта, который он обертывает. Затем, предположив, что вы используете его в программе, безопасной по типу, где бы вы ни находились Wrapper<String>, вы знаете, что обернутый объект является String.

Это не работает так хорошо, если вы хотите проверить конкретный класс обернутого объекта, однако, если класс для тестирования не равен final. В этом случае, вы можете передать на Class объект, что-то вроде этого:

<T> boolean compare(Wrapper<? super T> wrapper, Class<T> clazz) { 
    return wrapper.obj.getClass().equals(clazz); 
} 

Это проверяет класс обернутого объекта против указанного класса, что позволяет метод, который будет вызываться только в тех случаях, когда статический анализ позволяет что он может вернуться true.

Вы можете фактически объединить эти два подхода, если вы хотите, чтобы создать Wrapper класс, экземпляры которого могут содержать только члены определенного класса, в отличие от любого объекта, присваиваемые данного типа . Я не уверен, почему вы хотели бы это сделать.

Смежные вопросы