ClassCastException в наследовании - почему? - PullRequest
3 голосов
/ 09 января 2020

Следующий код выбрасывает ClassCastException:

Исключение в потоке "main" java .lang.ClassCastException: класс Child не может быть приведен к классу java .util.List (Child находится в безымянном модуле загрузчика 'app'; java .util.List находится в модуле java .base загрузчика 'bootstrap') в Test.main (Test. java: 20)

Я действительно не уверен, почему он так себя ведет. Я думаю, что написал правильный код.

public class Test {
    public void a(ParentI... ss) {
    }

    public void a(List<ParentI> ss) {
    }


    public <R extends ParentI> R makeParent() {
        ParentI ai = new Child();
        return (R) ai;
    }

    public static void main(String[] args) {
        Test al = new Test();
        al.a(al.makeParent());
    }
}


interface ParentI {
    public void a();
}

class Parent implements ParentI {
    public void a() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    public void a(int t) {
        System.out.println("child");
    }
}

Пожалуйста, помогите мне понять это и как это исправить.

Ответы [ 2 ]

3 голосов
/ 09 января 2020

Компилятор выводит тип, возвращаемый al.makeParent() в соответствии с методом a(), выбранным с помощью разрешения перегрузки метода.

Так как разрешение перегрузки метода сначала учитывает кандидатов, у которых нет аргументов vararg, учитывается только перегрузка public void a(List<ParentI> ss), и, следовательно, это выбранная перегрузка.

Причина public void a(List<ParentI> ss) может принять в качестве аргумента возвращаемое значение метода, который возвращает R extends ParentI, состоит в том, что может существовать класс, который расширяет ParentI и реализует List<ParentI>.

Как только перегрузка public void a(List<ParentI> ss) выбрана, приведение в return (R) ai; вызывает попытку приведения экземпляра Child к List, что не выполняется во время выполнения.

Если, например, вы изменили определение класса Child на:

class Child extends Parent implements List<ParentI>

Ваш код будет работать без исключения.

1 голос
/ 09 января 2020

пока у меня нет ответа относительно того, почему выбрасывается исключение. Мне удалось отредактировать код, чтобы программа работала успешно. метод makeParent() необходимо изменить, чтобы он не был универсальным c:

public ParentI makeParent() {
    ParentI ai = new Child();
    return ai;
}

, который в основном такой же, как и раньше.

тогда правильная перегрузка a() равна называется

...