На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Правила раздела Java FAQ
1. Данный раздел предназначен только для публикации готовых статей, с вопросами обращайтесь в соответствующие подразделы.
2. Все вопросы, связанные с ошибками или неточностями в представленных материалах направляйте модераторам персональным сообщением.
3. Все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут доступны остальным участникам после одобрения модераторами.
Модераторы: dark_barker, wind
  
> Проблемы компиляции массивов параметризованных типов, e.g. List<T>[] arr = new ArrayList<T>[32]
    Думаю, многие неоднократно удивлялись, почему компилятор не компилит код типа следующего:

    ExpandedWrap disabled
      List<T>[] arr = new ArrayList<T>[32]


    Проблема заключается в том, что исторически (еще задолго до Тигра) при операциях с массивами в java тип проверяется в рантайме. Т.е.:

    ExpandedWrap disabled
        A x = new A();
        A[] z = new B[] (...); //B subclass of A
              ...;
        z[i] = x; //присваивание выглядит корректно на этапе компиляции


    очевидно, что если б присваивание z[i] = x было разрешено, то семантика языка была бы нарушена - в массиве B[] появился бы элемент A. Скорее всего где-то дальше программа бы свалилась с неясными последствиями.
    Чтобы избежать подобных коллизий, было решено проверять корректность операций типа z[i] = x в рантайме. И все было хорошо.

    А потом пришел Тигр и приволок с собой generics и т.н. type erasure. Чтобы обеспечить хоть какую-то совместимость с legacy code, было решено удалять всю информацию о типах-параметрах на этапе компиляции, т.е. чтобы все эти <T> не попадали в байт-код вообще. Это и есть erasure. Хорошо это или плохо - это тема для HW, сейчас речь не об этом. Пока компилятор может проверить безопасность типов, все в порядке, т.к. эти семантические проверки работают еще до erasure.

    Проблема появляется в случае массивов и проверки в рантайме. Как проверить корректность присваивания в рантайме, если для этого нужен тип, а тип благополучно убран на этапе erasure? Ответ: никак. Решение: запретить создание массивов параметризуемых типов вообще.

    Теперь, надеюсь, понятно, почему это не компилится. Напоследок, маленькая иллюстрация, что бы могло быть, если бы компилировалось:

    ExpandedWrap disabled
        List<Integer>[] list = new ArrayList<Integer>[32]; //предположим, это бы компилировалось
        Object[] another_list = list;
        another_list[0] = new ArrayList<String>(16); // предупреждения нет!
        Integer s = list[0].get(0); // Ooops!


    Т.е. может произойти то, чего Sun в первую очередь старалась избежать - программа компилируется без ошибок и предупреждений, но не является безопасной с точки зрения типов.
    "Ever tried? Ever failed? No matter. Try again. Fail again. Fail better" (c) Samuel Beckett
    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
    0 пользователей:


    Рейтинг@Mail.ru
    [ Script Execution time: 0,0647 ]   [ 14 queries used ]   [ Generated: 19.08.19, 10:34 GMT ]