Ошибка компиляции Java, переопределяющая универсальный метод с универсальным параметром - PullRequest
0 голосов
/ 11 мая 2018
import java.util.Collection;

public abstract class A {

    public class R<T> { }

    public abstract <X> R<X> get1();

    public abstract <X> R<X> get2(Collection<String> p);

    public abstract <X> R<X> get3(Collection<Integer> p);

    public class B extends A {

        @Override
        public R<Object> get1() {
            return null;
        }

        @Override
        public R<Object> get2(Collection<String> p) {
            return null;
        }   

        @Override
        public <Object> R<Object> get3(Collection<Integer> p) {
            return null;
        }
    }
}

Метод get1 работает нормально, но есть ошибка компиляции для get2:

  • Метод get2 (Collection) типа A.B должен переопределить или реализовать метод супертипа

Эта ошибка возникает только с параметрами с обобщениями. get3 компилируется, но, конечно, есть предупреждение:

  • Параметр типа Object скрывает тип Object

Ясно, что есть и другие способы решить эту проблему, но, насколько я понимаю, это должно быть юридическим преимуществом, и мой вопрос больше в том, почему возникает эта ошибка компиляции. Заранее спасибо!

EDIT:

Извините, мой пример был недостаточно ясен. Поэтому здесь можно по-новому отреагировать на некоторые пункты ваших ответов.

public abstract class A {

    public abstract class R<T> { }

    public abstract <X> R<X> get();

    public abstract <Y> R<Y> get2(Collection<String> p);

    public abstract <Z> R<Z> get3(Collection<Integer> p);

    public class B extends A {

        @Override
        public R<String> get() {
            return null;
        }

        @Override
        public R<Double> get2(Collection<String> p) {
            return null;
        }   

        @Override
        public <V> R<V> get3(Collection<Integer> p) {
            return null;
        }
    }
}
  • Та же ошибка компиляции, что и выше для get2, и очевидное предупреждение о безопасности типа для get, которое я также ожидал получить на get2.
  • Я хочу, чтобы у каждого метода был свой тип, поэтому тип класса не является решением.
  • Использовать Object было плохим решением для этого примера, но это не было моей целью, и проблема скрытия типов для старого get3 ясна, как упомянуто выше.
  • Проблема заключается в подписи, как сказал лексикоре. Поэтому я прокомментирую его ответ.

Ответы [ 4 ]

0 голосов
/ 11 мая 2018

Как уже упоминалось в GhostCat , Object в get3 на самом деле является переменной типа. Это, как ни странно, то, что вы должны были использовать, но с запутанным именем.

Чтобы исправить свой внутренний класс, вы должны заново объявить параметры универсального типа для всех 3 методов:

public class B extends A
{
    @Override
    public <X> R<X> get1() {
        return null;
    }

    @Override
    public <X> R<X> get2(Collection<String> p) {
        return null;
    }

    @Override
    public <X> R<X> get3(Collection<Integer> p) {
        return null;
    }
}

Однако все это повторение <X> предполагает, что вы должны переместить параметр универсального типа в класс A. Вот как я бы это реализовал:

abstract class A<X>
{
    public class R<T> { }

    public abstract R<X> get1();

    public abstract R<X> get2(Collection<String> p);

    public abstract R<X> get3(Collection<Integer> p);

    public class B extends A<X>
    {
        @Override
        public R<X> get1() {
            return null;
        }

        @Override
        public R<X> get2(Collection<String> p) {
            return null;
        }

        @Override
        public R<X> get3(Collection<Integer> p) {
            return null;
        }
    }
}

Если B относится ко всем Object с (это не ясно из вашего примера), вы можете заменить приведенный выше внутренний класс на:

public class B extends A<Object>
{
    @Override
    public R<Object> get1() {
        return null;
    }

    @Override
    public R<Object> get2(Collection<String> p) {
        return null;
    }

    @Override
    public R<Object> get3(Collection<Integer> p) {
        return null;
    }
}
0 голосов
/ 11 мая 2018

Попробуйте

...
public <X> R<X> get2(Collection<String> p){
...
public <X> R<X> get3(Collection<Integer> p) {
...
0 голосов
/ 11 мая 2018

Ваш X универсальный тип не является и Object, а скорее чем-то, что расширяет Object, потому что на самом деле нет смысла заменять Object на Object. Действительный прототип для вашего метода get2:

// X or Y or any generic type or class
public <Y> R<Y> get2(Collection<String> p) {
    return null;
}

То же самое с вашим методом get3, вам не нужны универсальные элементы для манипулирования объектами, это должно быть что-то, что расширяет Object вместо

public <Y> R<Y> get3(Collection<Integer> p) {
     return null;
}
0 голосов
/ 11 мая 2018

Здесь:

public <Object> R<Object> get3(Collection<Integer> p) {

вероятно не , что вы имели в виду.

Вы вводите другую переменную типа , которая называется здесь Object.

Сравните это с:

public R<Object> get2(Collection<String> p) {

Другими словами: get2() использует java.lang.Object.get3() использует универсальный тип , который, к сожалению, называется Object.С таким же успехом вы могли бы написать

public <NONSENSE> R<NONSENSE> get3(Collection<Integer> p) {

И, наконец, get2() - это не то, чем вы бы занимались.Смотрите отличный ответ от Майкла для этой части.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...