<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210299&amp;view=findpost&amp;p=1763565</guid>
        <pubDate>Tue, 13 Nov 2007 23:03:17 +0000</pubDate>
        <title>Проблемы компиляции массивов параметризованных типов</title>
        <link>https://forum.sources.ru/index.php?showtopic=210299&amp;view=findpost&amp;p=1763565</link>
        <description><![CDATA[kl: Думаю, многие неоднократно удивлялись, почему компилятор не компилит код типа следующего:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">List&#60;T&#62;[] arr = new ArrayList&#60;T&#62;[32]</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Проблема заключается в том, что исторически (еще задолго до Тигра) при операциях с массивами в java тип проверяется в рантайме. Т.е.:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;A x = new A();</div><div class="code_line">&nbsp;&nbsp;A[] z = new B[] (...); //B subclass of A</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;...;</div><div class="code_line">&nbsp;&nbsp;z[i] = x; //присваивание выглядит корректно на этапе компиляции</div></ol></div></div></div></div><br>
<br>
очевидно, что если б присваивание z[i] = x было разрешено, то семантика языка была бы нарушена - в массиве B[] появился бы элемент A. Скорее всего где-то дальше программа бы свалилась с неясными последствиями. <br>
Чтобы избежать подобных коллизий, было решено проверять корректность операций типа z[i] = x в рантайме. И все было хорошо.<br>
<br>
А потом пришел Тигр и приволок с собой generics и т.н. type erasure. Чтобы обеспечить хоть какую-то совместимость с legacy code, было решено удалять всю информацию о типах-параметрах на этапе компиляции, т.е. чтобы все эти &lt;T&gt; не попадали в байт-код вообще. Это и есть erasure. Хорошо это или плохо - это тема для HW, сейчас речь не об этом. Пока компилятор может проверить безопасность типов, все в порядке, т.к. эти семантические проверки работают еще до erasure. <br>
<br>
Проблема появляется в случае массивов и проверки в рантайме. Как проверить корректность присваивания в рантайме, если для этого нужен тип, а тип благополучно убран на этапе erasure? Ответ: никак. Решение: <strong class='tag-b'>запретить создание массивов параметризуемых типов вообще</strong>. <br>
<br>
Теперь, надеюсь, понятно, почему это не компилится. Напоследок, маленькая иллюстрация, что бы могло быть, если бы компилировалось:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;List&#60;Integer&#62;[] list = new ArrayList&#60;Integer&#62;[32]; //предположим, это бы компилировалось</div><div class="code_line">&nbsp;&nbsp;Object[] another_list = list;</div><div class="code_line">&nbsp;&nbsp;another_list[0] = new ArrayList&#60;String&#62;(16); // предупреждения нет!</div><div class="code_line">&nbsp;&nbsp;Integer s = list[0].get(0); // Ooops!</div></ol></div></div></div></div> <br>
<br>
Т.е. может произойти то, чего Sun в первую очередь старалась избежать - программа компилируется без ошибок и предупреждений, но не является безопасной с точки зрения типов.]]></description>
        <author>kl</author>
        <category>Java FAQ</category>
      </item>
	
      </channel>
      </rss>
	