Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.128.199.88] |
|
Сообщ.
#1
,
|
|
|
Думаю, многие неоднократно удивлялись, почему компилятор не компилит код типа следующего:
List<T>[] arr = new ArrayList<T>[32] Проблема заключается в том, что исторически (еще задолго до Тигра) при операциях с массивами в java тип проверяется в рантайме. Т.е.: 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? Ответ: никак. Решение: запретить создание массивов параметризуемых типов вообще. Теперь, надеюсь, понятно, почему это не компилится. Напоследок, маленькая иллюстрация, что бы могло быть, если бы компилировалось: 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 в первую очередь старалась избежать - программа компилируется без ошибок и предупреждений, но не является безопасной с точки зрения типов. |