Java Generics: сравнение класса Object o с <E>
Скажем, у меня есть следующий класс:
public class Test<E> {
public boolean sameClassAs(Object o) {
// TODO help!
}
}
Как бы проверить, что o
- это тот же класс, что и E
?
Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false;
Я не могу изменить подпись метода из (Object o)
, поскольку я переопределяю суперкласс и поэтому не могу выбрать свою подпись метода.
Я также предпочел бы не идти по пути попытки броска, а затем поймать полученное исключение, если оно не получится.
Ответы
Ответ 1
У экземпляра Test
нет информации о том, что E
находится во время выполнения. Итак, вам нужно передать Class<E>
конструктору Test.
public class Test<E> {
private final Class<E> clazz;
public Test(Class<E> clazz) {
if (clazz == null) {
throw new NullPointerException();
}
this.clazz = clazz;
}
// To make things easier on clients:
public static <T> Test<T> create(Class<T> clazz) {
return new Test<T>(clazz);
}
public boolean sameClassAs(Object o) {
return o != null && o.getClass() == clazz;
}
}
Если вам нужна связь "instanceof", используйте Class.isAssignableFrom
вместо сравнения Class
. Примечание. E
должен быть неэквивалентным типом, по той же причине Test
нужен объект Class
.
Примеры в API Java см. в java.util.Collections.checkedSet
и т.д.
Ответ 2
Метод, который я всегда использовал, приведен ниже. Это боль и немного уродливая, но я не нашел лучшего. Вы должны передать тип класса через конструкцию, как при компиляции данных класса Generics.
public class Test<E> {
private Class<E> clazz;
public Test(Class<E> clazz) {
this.clazz = clazz;
}
public boolean sameClassAs(Object o) {
return this.clazz.isInstance(o);
}
}
Ответ 3
Я мог только заставить это работать следующим образом:
public class Test<E> {
private E e;
public void setE(E e) {
this.e = e;
}
public boolean sameClassAs(Object o) {
return (o.getClass().equals(e.getClass()));
}
public boolean sameClassAs2(Object o) {
return e.getClass().isInstance(o);
}
}
Ответ 4
Я просто пытался сделать то же самое, и один простой трюк, который я только что понял, - это то, что вы можете попробовать попробовать, и если приведение не выполнено, ClassCastException будет выброшено. Вы можете это поймать и сделать что угодно.
поэтому ваш метод sameClassAs должен выглядеть так:
public boolean sameClassAs(Object o) {
boolean same = false;
try {
E t = (E)o;
same = true;
} catch (ClassCastException e) {
// same is false, nothing else to do
} finally {
return same;
}
}