Я впервые использую дженерики в Java и сталкиваюсь с проблемой, которую не могу решить: почему это компилируется:
public interface Aa{}
public interface Bb{}
public interface Cc{}
public static <GenericAB extends Aa & Bb>
void method(GenericAB myABobject1, GenericAB myABobject2){}
public static <GenericAB extends Aa & Bb, GenericCA extends Cc & Aa>
void method(GenericAB myAbobject, GenericCA myCAobject){}
Но это не так:
public interface Aa{}
public interface Bb{}
public interface Cc{}
public static <GenericAB extends Aa & Bb>
void method(GenericAB myABobject1, GenericAB myABobject2){}
public static <GenericAB extends Aa & Bb, GenericAC extends Aa & Cc>
void method(GenericAB myAbobject, GenericAC myACobject){}
И я получаю такую ошибку: оба метода имеют одинаковое стирание.
Прошу прощения, если это глупый вопрос, но я не понимаю, почему порядок интерфейсов в объявлении параметра ограниченного типа кажется имеет значение. На самом деле я не думаю, что причиной ошибки является порядок, но я не понимаю, что именно.
Я читаю эта документация Oracle, он говорит, что я должен указать класс в качестве первого параметра, но Aa, Bb и Cc - все интерфейсы. Извините за мой английский тоже.




Важен порядок (§4.6):
The erasure of a type variable (§4.4) is the erasure of its leftmost bound.
GenericBC стирает либо до Aa, либо до Cc, в зависимости от того, что появляется первым (то есть крайним левым) в привязке.
Также см. учебник по стиранию типа и стирание типа, когда и что происходит Вопросы и ответы для объяснения стирания типа в целом.
В общем, мы не можем выполнять перегрузки с помощью универсальных шаблонов из-за правила «нет двух методов с одинаковым стиранием». Я собираюсь предположить, что причина, по которой это запрещено, связана с обратной совместимостью (старый код до дженериков с использованием нового пост-дженерикового кода). Я не думаю, что есть какие-то другие ограничения. Я думаю, что есть другие языки JVM, которые допускают такую перегрузку.
Хорошо, я читаю ссылки и начинаю понимать, хотя у меня все еще есть некоторые сомнения, но я думаю, что работа с ними - лучший способ к ним привыкнуть. Кстати, когда вы говорите «мы не можем делать перегрузки с помощью дженериков [...]», вы имеете в виду, что мы не должны этого делать или что это невозможно? Я спрашиваю об этом, потому что приведенный выше пример работает, и я перегружаю метод с помощью дженериков. Спасибо!
Запрещается иметь два метода с одинаковым именем и стиранием. (См. §8.4.8.3 под 1-м полужирным разделом, который начинается как «Это ошибка времени компиляции ...».) Например, void m(List<A> l) {} void m(List<B> l) {} будет ошибкой компилятора, потому что оба метода стирают в void m(List l) {}. Пример в вашем вопросе (где переменные типа стираются по-разному) - это просто довольно неясный частный случай.
Потому что во время выполнения после стирания типа оба метода имеют одинаковый заголовок.
public static <GenericAB extends Aa & Bb> void method(GenericAB myABobject1, GenericAB myABobject2){}
становится
public static void method(Aa myABobject1, Aa myABobject2){}
а также
public static <GenericAB extends Aa & Bb, GenericBC extends Aa & Cc>void method(GenericAB myAbobject, GenericBC myBCobject){}
становится
public static void method(Aa myAbobject, Aa myBCobject){}
оба результирующих метода имеют одинаковую подпись, что приводит к вашей ошибке
ИЗМЕНИТЬ после комментариев ниже параметры исправлены
@Radiodef спасибо, я исправил свой пример. Не заметил этого
Спасибо за ответ! Разве это не ограничивает? Или хотя бы сбивает с толку? Я имею в виду, если я хочу перегрузить функцию с помощью дженериков (как я сделал в примере с моим вопросом), почему я должен обращать внимание на порядок? Более того, не рискует ли этот механизм ограничить количество перегруженных методов в зависимости от количества интерфейсов, которые я хочу связать (я не могу прийти к примеру)? Я имею в виду, что если Oracle поступил так, конечно, для этого есть веская причина, но я не понимаю, какая именно. Кстати, завтра я обязательно прочту размещенные вами ссылки, я попытался прочитать их быстро, но они кажутся немного сложными. Спасибо!