Подтвердить что ты не робот

Java "new String [-1]" передает компиляцию. Как так?

Во время работы в Java я инициализировал новый массив String с отрицательной длиной. т.е. -

String[] arr = new String[-1];

К моему удивлению, компилятор не жаловался на это. Googling не вызвал никаких соответствующих ответов. Может ли кто-нибудь пролить свет на это?

Большое спасибо!

4b9b3361

Ответ 1

Причина в том, что JLS позволяет это, а компилятор, который помечен как ошибка компиляции, будет отклонять действительный код Java.

Он указан в JLS 15.10.1. Вот соответствующий фрагмент:

"... Если значение любого выражения DimExpr меньше нуля, тогда генерируется исключение NegativeArraySizeException."

Теперь, если компилятор Java помечает код как ошибку, тогда указанное поведение не может произойти... в этом конкретном коде.

Кроме того, нет текста, который я могу найти, что "разрешает" компилятор отклонить это в случаях "очевидной ошибки", связанных с постоянными выражениями времени компиляции, такими как -1. (И кто скажет, что это была ошибка?)


Следующий вопрос, конечно же, заключается в том, почему JLS это разрешает?

Вам нужно спросить дизайнеров Java. Однако я могу думать о некоторых (главным образом) правдоподобных причинах:

  • Это было изначально упущено, и нет сильного аргумента в его устранении. (Отмечая, что исправление этого прерывает совместимость исходного кода.)

  • Считалось, что это слишком необычный/краевой случай, с которым стоит иметь дело.

  • Это может вызвать проблемы для людей, пишущих генераторы исходного кода. (Представьте себе, что нужно писать код для оценки констант постоянной времени компиляции, чтобы вы не генерировали не компилируемый код. С текущей спецификацией JLS вы можете просто генерировать код с "плохим" размером и обрабатывать исключение (или нет), если код когда-либо выполняется.)

  • Возможно, у кого-то был план добавления "unarrays" в Java: -)


Другие ответы предположили, что компилятор мог/должен "указывать" этот случай. Если "flagging" означает вывод предупреждающего сообщения, это, безусловно, разрешено JLS. Тем не менее, это спорно, должен ли компилятор это сделать. С одной стороны, если вышеуказанный код был написан по ошибке, тогда было бы полезно, чтобы эта ошибка была отмечена. С другой стороны, если это не было ошибкой (или "ошибка" не была релевантной), то предупреждение было бы шумом или хуже. В любом случае, это то, что вам нужно обсудить с сопровождающим (-ами) для соответствующего компилятора (ов).

Ответ 2

Я не вижу причин, по которым это невозможно было исключить во время компиляции (по крайней мере, как предупреждение), так как это безоговорочно бросает NegativeArraySizeException при выполнении.

Я сделал несколько быстрых экспериментов с моим компилятором, и это кажется удивительно расслабленным в отношении такого рода вещей. Он не выдает предупреждения о делении целых чисел на ноль в постоянных выражениях, доступе к массиву вне пределов с постоянными индексами и т.д.

Из этого я заключаю, что общая схема здесь заключается в том, чтобы доверять программисту.

Ответ 3

Компилятор отвечает только за синтаксис , но не семантический смысл вашего кода. Таким образом, разумно, что компилятор не жалуется на ошибку, поскольку в вашем коде вообще нет синтаксической ошибки.

В Java массив выделяется в время выполнения, что абсолютно нормально. Если он выделяется во время компиляции, то как компилятор проверяет следующий код?

// runtime pass the length, with any value
void t(int length) {
   String[] stirngs = new String[length];
}

При передаче отрицательного значения как длины массива contruct будет выведено исключение во время выполнения.

public class Main {

    public static void main(String[] args) {
        String[] v = new String[-1];
    }
}

с ошибкой:

Exception in thread "main" java.lang.NegativeArraySizeException
    at Main.main(Main.java:5)

Ответ 4

Компилятор Java принимает целое число как длину массива. Это может быть переменная или константа времени компиляции. Длина массива устанавливается при создании массива. После создания его длина фиксирована.

Компилятор должен отмечать отрицательную константу времени компиляции как длину массива. Это просто не получается. Если длина является отрицательным числом, во время выполнения вы получите исключение NegativeArraySizeException.