Нет, дженерики в Java не работают таким образом.
С дженериками вы не можете делать ничего, что было бы невозможно без дженериков - вы просто избегаете писать много приведений, иКомпилятор гарантирует, что все безопасно (если вы не получаете некоторые предупреждения и не подавляете их).
Таким образом, для каждой переменной типа вы можете вызывать только методы, определенные в ее границах (без утки).
Кроме того, отсутствует генерация кода (кроме некоторых методов адаптера, которые делегируются методам с другими типами параметров для реализации универсальных типов).Предположим, у вас было что-то вроде этого
/**
* interface for objects who allow adding some other objects
*/
interface Addable<T> {
/** returns the sum of this object and another object. */
T plus(T summand);
}
Тогда мы могли бы создать наш метод sum
с двумя аргументами:
public static <T extends Addable<T>> T sum(T first, T second) {
return first.plus(second);
}
Статический метод компилируется в тот же байт-код, как этот (сдополнительная информация о типе в аннотациях):
public static Addable sum(Addable first, Addable second) {
return first.plus(second);
}
Это называется стирание типа .
Теперь этот метод можно вызывать для каждой пары из двух элементов добавляемого типа.Пример:
public class Integer implements Addable<Integer> {
public Integer plus(Integer that) {
return new Integer(this.value + that.value);
}
// private implementation details omitted
}
Здесь происходит следующее: компилятор создает дополнительный синтетический метод, подобный следующему:
public Object plus(Object that) {
return this.plus((Integer)that);
}
Этот метод будет вызываться только универсальным кодом с правамитипы, это гарантирует компилятору, если вы не выполняете небезопасных приведений куда-либо - тогда приведение (Integer)
здесь поймает ошибку (и сгенерирует ClassCastException).
Метод sum
теперь всегда вызывает метод plus
первого объекта, пути к этому нет.Нет кода, сгенерированного для каждого возможного аргумента типа (это является ключевым отличием дженериков Java и шаблонов C ++), поэтому мы не можем просто заменить один из сгенерированных методов специализированным.
Конечно, вы можете создать второй sum
метод, такой как предлагаемый неопровержимый (с перегрузкой), но он будет выбран, только если вы используете тип MyX
непосредственно в исходном коде, а не когдаВы вызываете метод sum
из некоторого другого универсального кода, который параметризован с помощью MyX, например:
public static <T extends Addable<T>> product (int times, T factor) {
T result = factor;
while(n > 1) {
result = sum(result, factor);
}
return result;
}
Теперь product(5, new MyX(...))
вызовет наш метод sum(T,T)
(который, в свою очередь, вызывает* Метод 1048 *, а не какой-либо перегруженный метод sum(MyX, MyX)
.
(JDK 7 добавляет новый режим диспетчеризации dynamic
метода, который позволяет специализацию для каждого аргумента во время выполнения, но это не используется Javaязык, предназначенный только для использования другими языками на основе JVM.)