2015-06-01 2 views
6

У меня есть довольно центральный класс, отвечающий за некоторые методы Utility. Я хотел, чтобы обеспечить дополнительную перегрузку для метода, который был объявлен следующим образом:Стирание коллекций generics и конфликтующих перегрузок

public static void removeDuplicated(Collection fullList, Collection itemsToRemove) { 
    //implementation stripped for brevity 
} 

Теперь, так как я не очень люблю Rawtypes, я указал коллекции из в наименьший общий знаменатель можно ожидать:

public static void removeDuplicated(Collection<Map<?,?>> fullList, 
    Collection<Map<?,?>> itemsToRemove) {} 

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

я продолжил писать заголовок метода для моей перегрузки:

public static <T extends TeObjectWrapper> void removeDuplicated(
    Collection<T> fullList, Collection<Map<?,?>> itemsToRemove) {} 

Это когда затмение (и впоследствии компиляции с javac6 через муравья) дал мне следующие сообщения об ошибке:

Стирание метод removeDuplicated(Collection<T>, Collection<? extends Map<?,?>>) такой же, как другой метод в типе [Утилиты-класс]

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

Теперь, как я понимаю, первая существующая перегрузка должна стереть до Collection<Map<Object, Object>>, а вторая - стереть до Collection<TeObjectWrapper>.

Единственным способом, которым это может быть одно и то же стирание, является то, что если TeObjectWrapper реализовал Map (или расширил один из классов реализации Map), но это не так. Это можно увидеть в супертипе иерархии TeObjectWrapper:

Supertype hierarchy: -TeObjectWrapper extends Object, implements <TeObjectAbstract implements TeBaseAbstract>

Почему компилятор рассматривать стираниям то же самое, и как я могу заставить его не думать?

+4

Стирание 'Collection ' '' 'Collection'. –

+0

Из-за стирания подпись метода одинакова. Мессинг с дженериками не меняет подпись метода. – user489041

ответ

6

Оба они стирают до public static void removeDuplicated(Collection, Collection). Вся параметризация стирается. Вам нужно будет дать им разные имена.

От 4.6. Type Erasure:

Тип стирание отображение [...] типов (которые никогда параметризованные типов или переменного типа).

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

Erasure означает: все общее исчезает.

(Но, как интересная побочная записка, общая информация являетсяpresent in the class file. Правило перегрузки связанно с тем, как спецификациями для Java дается, не обязательно, потому что это технически невозможно. Это больше из назад совместимость, чтобы позволить устаревшим не общим классам переопределять общие методы.Если исходные типы были удалены в будущей версии языка, могут быть разрешены такие перегрузки.)

+0

Я не думаю, что исходные тексты здесь являются корневыми задачами, но решение не создавать повторяющиеся джики (и, соответственно, стереть их). Для того, чтобы этот код работал так, как я думал, это потребует, чтобы Generics нужно было поддаваться проверке ... – Vogel612

+0

Выбор перегрузки выполняется статически во время компиляции, поэтому нет необходимости в полных повторных генериках, чтобы сделать это возможным. Истинные ограничения стирания больше связаны с тем, что мы можем сделать с переменной типа, например. если у нас есть класс MyClass {...} ', мы никогда не сможем использовать такие вещи, как' new T() 'и' obj instanceof T', потому что 'MyClass ' и' MyClass ' компилируются в те же байт-коды. – Radiodef

Смежные вопросы