Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 208
Tom Teman Avatar asked May 17 '12 13:05

Tom Teman


3 Answers

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).

like image 58
Stephen C Avatar answered Oct 20 '22 21:10

Stephen C


I see no reason why this couldn't be flagged up at compile time (at least as a warning), since this unconditionally throws NegativeArraySizeException when executed.

I've done some quick experiments with my compiler, and it seems surprisingly relaxed about this sort of thing. It issues no warning about integer divide by zero in constant expressions, out-of-bounds array access with constant indices etc.

From this I conclude that the general pattern here is to trust the programmer.

like image 2
NPE Avatar answered Oct 20 '22 22:10

NPE


Compiler only responsible for checking language syntax, but not the semantic meaning of you code. Thus it is reasonable the compiler is not complaining error as there is no syntax error in your code at all.

In Java, array is allocated at runtime, which is absolutely ok. If it is allocate at compile time, then how compiler check the following code?

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

When pass negative value as length to contruct array, the runtime exception will being thrown.

public class Main {

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

with error:

Exception in thread "main" java.lang.NegativeArraySizeException
    at Main.main(Main.java:5)
like image 1
Pau Kiat Wee Avatar answered Oct 20 '22 20:10

Pau Kiat Wee