Подтвердить что ты не робот

Имя генерации дженериков Java, имеет такое же стирание

У меня есть суперкласс Foo. И класс-бар, расширяющий его.

public class Bar extends Foo

Функция в Foo:

protected void saveAll(Collection<?> many)

Функция в баре:

public void saveAll(Collection<MyClass> stuff) {
   super.saveAll(stuff);
}

Получение ошибки:

 Name clash: The method saveAll(Collection<MyClass>) of type Bar has the same erasure as saveAll(Collection<?>) of type Foo but does not override it.

Что я делаю неправильно?

4b9b3361

Ответ 1

Вы переопределяете метод saveAll несовместимым типом. Возможно, вы хотите сделать что-то вроде:

public class Bar extends Foo<MyClass>

Функция в Foo<E>

protected void saveAll(Collection<E> many)

и функция в баре:

public void saveAll(Collection<MyClass> stuff) {
   super.saveAll(stuff);
}

Ответ 2

Из-за функции стирания типа Java Java JVM не сможет узнать, является ли это метод с параметризованным типом MyClass или первым, который должен быть вызван.

Если возможно или применимо, наиболее часто используемый шаблон, который я видел, чтобы избежать этого, заключается в том, чтобы изменить класс Foo, чтобы иметь параметризованный тип:

public class Foo<T> {
    protected void saveAll(Collection<T> many) {}
}

а затем Bar просто реализует Foo для вашего конкретного типа:

public class Bar extends Foo<MyClass> {
    public void saveAll(Collection<MyClass> many) {
        super.saveAll(many);
    }
}

Ответ 3

Во время выполнения типы параметров заменяются на Object. Итак, saveAll(Collection<?>) и saveAll(Collection<MyClass>) преобразуются в saveAll(Collection). Это столкновение имен. Подробнее см. здесь.

Вы можете сделать это:

public class Foo<T> {
    protected void saveAll(Collection many) {
        // do stuff
    }
}

public class Bar extends Foo<MyClass> {
}

Ответ 4

Когда компиляторы компилируются в байтовый код, происходит процесс с именем Erasure. Это удаляет информацию о типе из коллекций. Я считаю, что он будет вручную выполнять трансляции и т.д. Как часть процесса генерации байтового кода. Если вы удалите общие части своего класса (например, <.. > ), вы увидите, что у вас есть два метода saveAll. Ошибка в том, что у вас есть два варианта сохранения всех методов. Коллекции имеют объект типа в байтовом коде.

Попробуйте удалить <.. > , который может сделать его более понятным. Когда вы вернете <... > назад, рассмотрите имя методов. Если они разные, они должны компилироваться.

Также я не думаю, что это проблема спящего режима, поэтому этот тег следует удалить. У вас есть общая проблема java.

Что вы можете сделать здесь: введите класс

public class Bar extends Foo<MyClass>

а затем типы методов с T

public void saveAll(Collection<MyClass> stuff) {
   super.saveAll(stuff);
}

а затем объявление Foo будет чем-то вроде

public abstract class Bar extends Foo<T> {
    public void saveAll(Collection<T> stuff) {
}

Ответ 5

Вы просто переопределяете методы с разными сигнатурами.

Будет хорошей идеей использовать правило PECS (Producer - Extends, Consumer - Super), описанное в "Эффективном Java Second Edition" Джошуа Блоха.

в соответствии с этим правилом он должен выглядеть следующим образом.

В классе Foo:

public class Foo<E>{

protected void saveAll(Collection<? super E> many){....}

protected void getAll(Collection<? extends E> many){....}

}

Ответ 6

В то время как существующие ответы верны, эта ошибка возникает, когда вы объявляете фактический тип не в разделе "extends...", а в имени фактического класса:

Неправильно:

public class Bar<MyClass> extends Foo
{
    ...
}

Правильно:

public class Bar extends Foo<MyClass>
{
    ...
}