Дженерики Java:Сравнение класса объекта o с <E>

StackOverflow https://stackoverflow.com/questions/51582

  •  09-06-2019
  •  | 
  •  

Вопрос

Допустим, у меня есть следующий класс:

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) поскольку я переопределяю суперкласс и поэтому не могу выбрать сигнатуру своего метода.

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

Это было полезно?

Решение

Пример 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 и подобное.

Другие советы

Метод, который я всегда использовал, приведен ниже.Это больно и немного некрасиво, но лучшего я не нашел.Вам необходимо передать тип класса при построении, так как при компиляции 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);
    }
}

Я мог заставить его работать только так:

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);  
    }
}

Я просто пытался сделать то же самое, и я только что понял один хитрый трюк: вы можете попробовать приведение, и если приведение не удастся, будет выброшено 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;
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top