2013-07-05 2 views
1

У меня есть метод, который использует общий интерфейс класса в качестве аргумента, я хотел бы проверить, что предоставленный интерфейс расширяет некоторый базовый класс, если он не будет вызывать исключение. Можно ли сделать что-то похожее на:Можно ли оценить, расширяет ли интерфейс класса определенный базовый класс?

public void genericMethod(Class<T> c) { 
    if (!(c instanceof baseClass)) { 
     throw new Exception("Must be instance of base class"); 
    } 
} 

Даже если это возможно, считалось бы это хорошей практикой? Или должны ли java generics следовать тем же принципам ducktyping?

ответ

5

Вы можете использовать Class.isAssignableFrom:

if (baseClass.isAssignableFrom(c)) { 
    ... 
} 

Этот код предполагает, что baseClass переменная (поле, локальная переменная, независимо) типа Class. Если baseClass - это имя класса (которое было бы против соглашений Java), то вместо этого используйте baseClass.class, как предложено Pshemo в комментариях.

Из документации:

Определяет, является ли класс или интерфейс, представленный этим объектом класса является либо такой же, как, или суперкласс или суперинтерфейс, класс или интерфейс, представленное указанным параметром класса.

+2

Чтобы быть более точным 'baseClass.class.isAssignableFrom (с) '. Во всяком случае +1 – Pshemo

+0

О, я понимаю, о чем вы. Тем не менее, нет единого, общего решения: если 'baseClass' является' Class' (как я предполагал первоначально, на основе соглашений Java), вы не должны использовать '.class'. Если это * имя * класса, то вы должны использовать '.class'. Чтобы быть более точным, если 'baseClass' является именем класса, тогда код, который я изначально написал, даже не компилируется; однако, если это переменная типа 'Class', тогда ваш код даже не будет компилироваться. –

+0

Поскольку OP использовал 'instanceof baseClass', я предположил, что' baseClass' является именем интерфейса, а не ссылкой на класс, но все возможно на SO questins :) – Pshemo

3

Для решения основной части вашего вопроса; в то время как вы собираетесь путь дженериков, он будет выглядеть лучше, если вы только что:

 public void genericMethod(Class<? extends BaseClass> c) { 
      // do what you want 
     } 

? символ подстановки сообщает компилятору, что только дочерние классы BaseClass являются приемлемыми аргументы, по существу, выполняя instanceOf проверку вы.

Это в значительной степени исключает возможность злоупотребления вашего метода во время компиляции

См также