Можно записать специальное средство выделения "кучи" для определенных размеров объектов, которое очень производительно. Однако общий средство выделения "кучи" не особенно производительно.
Также я соглашаюсь с TorbjГ¶rn Gyllebring об ожидаемом времени жизни объектов. Положительная сторона!
Может показаться нелогичным, что исключение могло произойти в строке a = 1, но могла возникнуть ошибка JVM. Таким образом, оставив переменную неинициализированной. Итак, ошибка компилятора имеет смысл. Это та неясная ошибка времени выполнения, о которой вы упомянули. Однако я бы сказал, что OutOfMemoryError далеко не непонятен и разработчики должны хотя бы подумать о нем. Кроме того, помните, что состояние, которое устанавливает OutOfMemoryError, может произойти в другом потоке, и единственное действие, которое выталкивает объем памяти кучи, превышающий предел, - это присвоение переменной a.
В любом случае, поскольку вы смотрите на компилятор design, я также предполагаю, что вы уже знаете, насколько глупо возвращать значения в блоке finally.
Спецификация языка Java требует, чтобы переменная была назначена перед ее использованием. JLS
определяет особые правила для правил, известных как правила «Определенного назначения». Все компиляторы Java должны их придерживаться.
V определенно назначается перед блоком finally, если и только если V определенно назначается перед оператором try.
Другими словами, при рассмотрении оператор finally, операторы блока try и catch внутри оператора try-catch-finally
не рассматриваются.
Излишне говорить, что эта спецификация здесь очень консервативна, но они предпочли бы спецификация должна быть простой, но немного ограниченной (полагаю, что правила уже сложны), чем быть снисходительной, но трудной для понимания и рассуждений.
Компиляторы должны следовать этим правилам определенного присвоения, поэтому все компиляторы выдают одни и те же ошибки. Компиляторам не разрешается выполнять какой-либо дополнительный анализ, кроме указанного в JLS
, для подавления любых ошибок.
Я считаю, что это просто из-за семантики отношения «попробуй-поймай-наконец». Из Спецификации языка Java :
Если выполнение блока try завершается нормально, затем наконец блок выполняется ...
Если выполнение блока try завершается внезапно из-за броска значения V ...
Если выполнение блока try завершается внезапно для любого другого причина R, то блок finally казнен ...
Последний случай кажется здесь наиболее актуальным. Кажется, что блок finally должен иметь возможность правильно выполняться, если блок try завершается внезапно по ЛЮБОЙ причине. Очевидно, что если блок try закончится до назначения, блок finally будет недействителен. Хотя, как вы сказали, это маловероятно.
Весьма вероятно, что javac требуется, чтобы сделать общее предположение, что исключение может произойти в любой точке блока try, даже во время присваивания, и что, следовательно, finally может вернуть неинициализированную переменную. Теоретически он мог бы провести подробный анализ и обнаружить, что на всех путях, проходящих через блок попытки, «a» всегда будет успешно инициализироваться, но это трудоемкая работа практически без выгоды.
Теперь, если кто-то просто может указать на соответствующий раздел в Спецификации языка Java ...
Я предполагаю, что компилятор Java предполагает худший случай - нет гарантии, что что-либо в блоке try даже выполняется по какой-либо причине. Итак, его жалоба действительна. Переменная могла не быть инициализирована.