Скажем, у меня есть следующий класс:
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), поскольку я переопределяю суперкласс и поэтому не могу выбирать свою сигнатуру метода.
Я бы также предпочел не пытаться выполнить приведение, а затем перехватить полученное исключение, если оно не удастся.




Я мог заставить его работать только так:
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);
}
}
Метод, который я всегда использовал, приведен ниже. Это неприятно и немного некрасиво, но я не нашел лучшего. Вы должны передать тип класса при построении, так как при компиляции 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);
}
}
Экземпляр 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.
Примеры в Java API см. В java.util.Collections.checkedSet и аналогичных.
Они эквивалентны. IMO == легче читать (хотя это означает, что читатель должен знать о типе). Это немного быстрее до встраивания. Теперь то, что я, кажется, не тестировал, - это null clazz.
Я просто пытался сделать то же самое, и я только что понял одну хитрую уловку: вы можете попробовать приведение, и если приведение не удастся, будет сгенерировано исключение 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;
}
}
Нет, не будет. Это непроверенный состав. Он никогда не вызовет исключения. Во время выполнения «t» имеет тип стирания E, то есть просто Object, поэтому приведение не выполняется.
Ты прав. Это сэкономит мне массу времени на устранение неполадок в дальнейшем, потому что компиляция кажется прекрасной.
Я бы лучше сравнил классы с равными. Или есть особая причина использовать ==?