почему методы моста в Java не предотвращают это и не создают исключение? - PullRequest
0 голосов
/ 15 февраля 2019

почему приведенный ниже обобщенный код не генерирует исключение во время выполнения?

public static void main(String[] args) {
        ((List)new ListString()).add(3);
    }


    static class ListString extends ArrayList<String>{

    }

Я понимаю, что это НЕ то, как следует использовать обобщенные значения, но я думал, что методы моста потребуютпроблемы, добавив приведенный ниже метод, который выдает ClassCastException.

public boolean add(Object o){
      return add((E)o);
}

Примечание: это действительно вызывает исключение ClassCastException, если я изменю класс ListString в соответствии с приведенным ниже описанием:

static class ListString extends ArrayList<String>{
        @Override
        public boolean add(String o){
            return super.add(o);
        }
    }

1 Ответ

0 голосов
/ 15 февраля 2019

Мосты (синтетические методы) не создаются, если вы на самом деле не пишете метод, как вы это делали в своем последующем тесте, в котором вы указали public boolean add(String o){return super.add(o);} в коде.

Когда вы вызываете .get(someInt) навыражение типа StringList, компилятор может видеть, что ваш тип StringList, даже если это подтип ArrayList<String>, не имеет метода с сигнатурой String get(int).Следовательно, он генерирует вызов метода Object get() в байт-коде и, кроме того (если необходимо), приведение типов и на стороне java действует так, как если бы метод get для StringList возвращает String.Даже если на уровне байт-кода это не так.

Если затем сделать так, чтобы появился метод String get(int), например, путем подкласса StringList или путем редактирования исходного кода и перекомпиляции только этого файла, тогда и только тогдаявляется сгенерированным методом моста.Поскольку Java является динамической диспетчеризацией, этот мост всегда используется.Мост бросает и вызывает (или вызывает и бросает, зависит от того, покрывает ли мост shenanigans возвращаемого типа или shenanigans параметра).

Вы можете проверить все это, используя javap -v: я настоятельно рекомендую всем, кому это интереснои хочу точно знать, как это работает, развлекаясь, исследуя разницу в результатах между этим:

import java.util.*;

public class Test extends ArrayList<String> {
    public static void main(String[] args) {
        List raw = new Test();
        raw.add(3);
    }
}

и этим:

import java.util.*;

public class Test extends ArrayList<String> {
    public static void main(String[] args) {
        List raw = new Test();
        raw.add(3);
    }
    public boolean add(String o) {
        return super.add(o);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...