Tom Teman Tom Teman - 1 month ago 7
Java Question

Java "new String[-1]" passes compilation. How come?

While fiddling around in Java, I initialized a new String array with a negative length.
i.e. -

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


To my surprise, the compiler didn't complain about it.
Googling didn't bring up any relevant answers. Can anyone shed some light on this matter?

Many thanks!

Answer

The reason is that the JLS allows this, and a compiler that flagged it as a compilation error would be rejecting valid Java code.

It is specified in JLS 15.10.1. Here's the relevant snippet:

"... If the value of any DimExpr expression is less than zero, then a NegativeArraySizeException is thrown."

Now if the Java compiler flagged the code as an error, then that specified behaviour could not occur ... in that specific code.

Furthermore, there's no text that I can find that "authorizes" the compiler to reject this in the "obvious mistake" cases involving compile-time constant expressions like -1. (And who is to say it really was a mistake?)


The next question, of course, is 'why does the JLS allow this?'

You've need to ask the Java designers. However I can think of some (mostly) plausible reasons:

  • This was originally overlooked, and there's no strong case for fixing it. (Noting that fixing it breaks source code compatibility.)

  • It was considered to be too unusual / edge case to be worth dealing with.

  • It would potentially cause problems for people writing source code generators. (Imagine, having to write code to evaluate compile-time constant expressions in order that you don't generate non-compilable code. With the current JLS spec, you can simply generate the code with the "bad" size, and deal with the exception (or not) if the code ever gets executed.)

  • Maybe someone had a plan to add "unarrays" to Java :-)


Other answers have suggested that the compiler could / should "flag" this case. If "flagging" means outputting a warning message, that is certainly permitted by the JLS. However, it is debatable whether the compiler should do this. On the one hand, if the above code was written by mistake, then it would be useful to have that mistake flagged. On the other hand, if it was not a mistake (or the "mistake" was not relevant) then the warning would be noise, or worse. Either way, this is something that you would need to discuss with the maintainer(s) for the respective compiler(s).