26

Java をいじっているときに、新しい String 配列を負の長さで初期化しました。すなわち -

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

驚いたことに、コンパイラはそれについて文句を言いませんでした。グーグルは関連する答えをもたらしませんでした。誰でもこの問題に光を当てることができますか?

どうもありがとう!

4

4 に答える 4

25

その理由は、JLS がこれを許可しており、コンパイル エラーとしてフラグを立てたコンパイラが有効な Java コードを拒否するためです。

JLS 15.10.1で指定されています。関連するスニペットは次のとおりです。

「... DimExpr 式の値がゼロ未満の場合、NegativeArraySizeException がスローされます。」

Javaコンパイラがコードにエラーとしてフラグを立てた場合、その特定の動作は発生しません...その特定のコードで。

さらに、 のようなコンパイル時の定数式を含む「明らかな間違い」の場合に、コンパイラがこれを拒否することを「承認」するテキストは見つかりません-1。(そして、それが本当に間違いだったと誰が言えますか?)


もちろん、次の質問は、「JLS がこれを許可する理由」です。

Java 設計者に尋ねる必要があります。ただし、いくつかの(ほとんどの)もっともらしい理由を考えることができます。

  • これはもともと見落とされていたものであり、修正する確固たる理由はありません。(これを修正すると、ソース コードの互換性が損なわれることに注意してください。)

  • 対処する価値があるにはあまりにも珍しい/エッジケースであると考えられていました.

  • これは、ソース コード ジェネレーターを作成する人々に問題を引き起こす可能性があります。(コンパイルできないコードを生成しないように、コンパイル時の定数式を評価するコードを書かなければならないことを想像してみてください。現在の JLS 仕様では、単純に「不適切な」サイズのコードを生成し、コードが実行された場合は例外 (または例外)。

  • 誰かがJavaに「unarrays」を追加する計画を持っていたのかもしれません:-)


他の回答は、コンパイラがこのケースに「フラグを立てる」ことができる/すべきであることを示唆しています。"flagging" が警告メッセージの出力を意味する場合、それはJLS によって確実に許可されています。ただし、コンパイラがこれを行うべきかどうかは議論の余地があります。一方では、上記のコードが間違って書かれた場合、その間違いにフラグを立てると便利です。一方、それが間違いでなかった場合 (または「間違い」が関連していなかった場合)、警告はノイズになるか、さらに悪いことになります。いずれにせよ、これはそれぞれのコンパイラのメンテナーと話し合う必要があるものです。

于 2012-05-17T13:14:20.993 に答える
2

これは実行時に無条件にスローNegativeArraySizeExceptionされるため、コンパイル時に (少なくとも警告として) フラグを立てることができなかった理由はわかりません。

私は自分のコンパイラでいくつかの簡単な実験を行いましたが、この種のことについては驚くほどリラックスしているようです。定数式でのゼロによる整数除算、定数インデックスを使用した範囲外の配列アクセスなどに関する警告は発行されません。

このことから、ここでの一般的なパターンはプログラマーを信頼することであると結論付けています。

于 2012-05-17T13:18:20.507 に答える
1

コンパイラは言語構文のチェックのみを担当しますが、コードのセマンティックな意味は担当しません。したがって、コードに構文エラーがまったくないため、コンパイラがエラーを訴えていないのは当然です。

Javaでは、配列は実行時に割り当てられますが、これはまったく問題ありません。コンパイル時に割り当てられる場合、コンパイラは次のコードをどのようにチェックしますか?

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

構成配列の長さとして負の値を渡すと、実行時例外がスローされます。

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)
于 2012-05-17T13:26:28.590 に答える
0

Java コンパイラは、配列の長さとして整数を取ります。変数またはコンパイル時の定数にすることができます。配列の長さは、配列の作成時に確立されます。作成後、その長さは固定されます。

コンパイラは、負のコンパイル時定数に配列の長さとしてフラグを立てる必要があります。そうしないだけです。長さが負の数の場合、実行時に NegativeArraySizeException が発生します。

于 2012-05-17T13:18:15.340 に答える