а также

есно, почему это корректное переопределение:

public abstract class A {

    public abstract <X> Supplier<X> getSupplier();

    public static class B extends A {

        @Override
        public Supplier<String> getSupplier() {
            return String::new;
        }
    }
}

Тогда как это не так:

public abstract class A {

    public abstract <X> Supplier<X> getSuppliers(Collection<String> strings);

    public static class B extends A {

        @Override
        public Supplier<String> getSuppliers(Collection<String> strings) {
            return String::new;
        }
    }
}

Согласно сJLS §8.4.8.1, B.getSupplier должна быть подписьA.getSupplier:

Метод экземпляра mC, объявленный или унаследованный классом C, переопределяет из C другой метод mA, объявленный в классе A, если все следующее верно:

...Подпись mC является подписью (§8.4.2) подписи mA....

Подписи определены вJLS §8.4.2:

Два метода или конструктора, M и N, имеютта же подпись если они имеют одинаковое имя, одинаковые параметры типа (если они есть) (§8.4.4) и после адаптации формальных параметров типа N к параметрам типа M одинаковые формальные параметры.

Сигнатура метода m1 является подписью метода m2, если либо:

m2 имеет такую ​​же подпись, как m1, илиподпись m1 такая же, как стирание (§4.6) подписи m2.

Так похожеB.getSupplier это подписьA.getSupplier ноB.getSuppliers являетсяне подписьA.getSuppliers.

Интересно, как это может быть.

ЕслиB.getSupplier это подписьA.getSupplier потому что он имеет то же самое стирание, тоB.getSuppliers также должно иметь такое же стирание, что иA.getSuppliers, Этого должно хватить для переопределенияgetSuppliers быть законным - но это не так.

ЕслиB.getSupplier это подписьA.getSupplier поскольку он имеет одну и ту же сигнатуру, мне интересно, что именно означает «параметры одного типа (если они есть)».

Если рассматриваются параметры типа, то они должны иметь разные параметры типа:A.getSupplier имеет параметр типаX, B.getSupplier не имеет ни одного
Если параметры типа не учитываются, то какgetSuppliers разные?

Это скорее академический вопрос о переопределениях и обобщениях, поэтому, пожалуйста, не предлагайте рефакторинг кода (например, параметр типа перемещения).X в класс и т. д.).

Я ищу формальный ответ на основе JLS.

С моей точки зренияB.getSupplier не должно быть в состоянии переопределитьA.getSupplier поскольку они не имеют одинаковые параметры типа. Это делает следующий код (который производитClassCastException) законно:

A b = new B();
URL url = b.<URL>getSupplier().get();

Ответы на вопрос(2)

Ваш ответ на вопрос