Есть проблема, потому что компилятор должен использовать стирание параметризованных типов для ваших методов. Так как T
и E
не попадают в среду выполнения, компилятор систематически заменяет типы параметров вашего метода.
В соответствии с руководством (отметьте this и this ), параметры неограниченного типа заменяются на Object
, и ограничения применяются для параметров ограниченного типа.
Это означает, что ваши сигнатуры метода скомпилированного интерфейса выглядят так:
public interface DBInterface {
public int delete(Object element);
public int delete(Object example);
}
И ваша вторая версия:
public interface DBInterface<T extends DatabaseObject, E> {
public int delete(DatabaseObject element);
public int delete(Object example);
}
Я полагаю, что это делает проблему очевидной для вашего первого фрагмента кода.
Как я могу объявить T и E в интерфейсе, чтобы гарантировать, что они не будут одного типа?
Этот вопрос не может принять безусловный ответ. Фактический ответ зависит от значения T
и E
. Например, не имеет смысла предлагать, чтобы эти параметры типа были ограничены по-разному, потому что в некоторых случаях это может не иметь смысла.
С учетом вышесказанного вы должны рассмотреть вопрос о переименовании методов: я не могу вспомнить DBInterface
с двумя одинаково типизированными параметрами, которые не играют разных ролей. Например, методы могут быть:
public int deleteById(T element);
public int deleteByKey(E key);
Другими словами, если бы мы забыли об однобуквенном соглашении об именах общих типов, что бы вы назвали параметрами вашего типа?
public interface DBInterface<IdColumnType, PKColumnType> {}
Я не понимаю, почему это не должно применяться к именам ваших методов, вы должны признать, что, в конце концов, вы разрешили своим пользователям передавать один и тот же класс для обоих аргументов типа ... (то есть что технически у вас все еще есть проблема, даже если компилятор не выполняет стирание типа)