33

I noticed one could write code like this, which is perfectly normal, by the way:

int arrays[] = {1, 2, 3};
for (int n : arrays)
   System.out.println(n);

But I don't see how the following is illegal:

for (int n : {1, 2, 3})
   System.out.println(n);

From a compiler writer's point of view, this does not introduce any ambiguity, does it? The type of the array can be expected to be the same type as the element declared previously. In other words, n is declared as int, so the array must be int[]

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
One Two Three
  • 22,327
  • 24
  • 73
  • 114

5 Answers5

36

You need this syntax:

for(int n : new int[]{1, 2, 3})
   System.out.println(n);
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • Why is `new int[]` needed? In the array declaration, it wasn't needed, was it? Or is it that the java compiler/parser automatically add `new int[]` to the declaration? – One Two Three Apr 22 '13 at 05:29
  • When you want to construct object you have to start with 'new' keyword. Here int array is an object as well. – Shamim Ahmmed Apr 22 '13 at 09:14
  • 7
    That's not the reason - see the first example. The reason is that in the second example the compiler doesn't know what type `{1,2,3}` is. As to *why* - that's just a design decision. An alternative would be some form of type inference, i.e. guessing what the type should be. – mikołak Apr 22 '13 at 10:38
  • 1
    @OneTwoThree just brackets are a block declaration. By them self they just set the scope. On the other-hand [] states that this is an array. – Mite Mitreski Apr 22 '13 at 14:29
  • this allocates a `new` array every time, right? the original code with the variable declaration does not, right? – sds Apr 22 '13 at 16:01
  • @sds, this shouldn't allocate a new array on every iteration, if that's what you mean by `every time` should it? – Mike Perrenoud Apr 23 '13 at 17:49
  • @MichaelPerrenoud: of course I mean that a new array is allocated on every call to the surrounding block, not on each of the 3 iterations. – sds Apr 23 '13 at 17:51
  • @sds java arrays are always mutable, the code has to allocate a new array every time the code is invoked (afaik compilers for languages with const semantics like C and C++ also reallocate arrays declared like this every time) – josefx Apr 28 '13 at 12:23
  • @josefx: IIUC, one can allocate a fixed size array on the stack in C – sds Apr 29 '13 at 14:51
  • @sds that removes the allocation cost itself, however the array still has to be initialized every time the stack space for it is allocated. – josefx Apr 29 '13 at 18:23
36

From the Java Language Specification, §10.6 - Array Initializers:

An array initializer is written as a comma-separated list of expressions, enclosed by braces { and }.

A trailing comma may appear after the last expression in an array initializer and is ignored.

Each variable initializer must be assignment-compatible (§5.2) with the array's component type, or a compile-time error occurs.

It is a compile-time error if the component type of the array being initialized is not reifiable (§4.7).

An array initializer is part of an array creation expression, which does define that you require one of these four forms to successfully initialize an array:

ArrayCreationExpression:
    new PrimitiveType DimExprs Dimsopt
    new ClassOrInterfaceType DimExprs Dimsopt
    new PrimitiveType Dims ArrayInitializer 
    new ClassOrInterfaceType Dims ArrayInitializer

Again, from the specs:

It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (§4.7). Otherwise, the ClassOrInterfaceType may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type (§9).

This is why you require the syntax new int[] {1, 2, 3}.

EDIT: To get more into the nuances of your question:

From a compiler writer's point of view, this does not introduce any ambiguity, does it? The type of the array can be expected to be the same type as the element declared previously. In other words, n is declared as int, so the array must be int[]

No. There is ambiguity. As a for-instance, what is the difference between the following two statements?

int[] arr1 = new int[] {1, 2, 3};
short[] arr2 = new short[] {1, 2, 3};

The major difference is what they compile down to in bytecode. One is obviously an int, the other is obviously a short. However, without the ability to tell which data type is which (without the values in the array exceeding Short.MAX_VALUE), it would be impossible to assert that, this array, beyond a shadow of a doubt, is an int. Recall that a short falls into the range of an int, so you can easily get into some tricky/bizarre scenarios when using that.

It gets more fun: this is valid code.

for(int i : arr2) {
    System.out.println(i);
}

Again, as long as the elements in arr2 don't exceed Short.MAX_VALUE, you can get away with this ambiguous reference between short and int.

This is another reason why the compiler can't just infer that you mean int. You could mean short.*

*: Not that many people ever would, but that's just in case there are that do.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • To extend a bit on the ambiguity part -- I've been asked on occasion "but what about `{"str1", "str2", "str2"}`, that's definitely String[]?" -- and it's not. In Java everything (short of the primitives) inherits from `Object`, so even by `{"str1", "str2"}` you could be meaning either `String[]` or `Object[]`. – TC1 Apr 22 '13 at 13:57
  • I would argue that you're correct, with a caveat. You can't instantiate an `Object` in that way, but it could easily be a `ClassOrInterfaceType` that takes a constructor argument of ` String`. – Makoto Apr 22 '13 at 19:22
7

Because arrays are objects, and have to be instantiated. Java does not recognize {} by itself as an array. It does, however, permit you to use a code block (i.e. code in {..}) to define the initial elements of the array.

The way you accomplish this is described by the answer above.

Chris Chambers
  • 1,367
  • 21
  • 39
  • Yeah, I see your point... I suppose the compiler/parser could be a bit smarter! – One Two Three Apr 22 '13 at 05:30
  • Well, that would require Java to distinguish between a regular block of code and an array initialization, which would be tricky to say the least. – Chris Chambers Apr 22 '13 at 05:31
  • No, but this is within the two parens of a for-each loop. There is no ambiguity here, is there? (Sorry, I'm a compiler person :D, and I tend to notice this kind of stuff) – One Two Three Apr 22 '13 at 05:32
  • You could theoretically have an anonymous method in there I think. Also, detecting this would just add more overhead and its probably not worth it. – Chris Chambers Apr 22 '13 at 05:33
  • 7
    It would also have to work out with possibly zero context whether you meant new byte[], new char[], new short[], new int[], or new long[]. Which it can't. So it could only be legal in contexts where there was enough type context. Which would mean it would be legal syntactically but illegal semantically in some contexts. You can see where this is going. – user207421 Apr 22 '13 at 05:34
  • EJP: Yeah, that's going to be the major problem: what type of array are you defining. – Chris Chambers Apr 22 '13 at 05:36
  • We could expect the array to have the same type as the type of the element declared previously. `for ( )` – One Two Three Apr 22 '13 at 05:37
  • What if there isn't one? What about Object o = {1,2,3}? What about a parameter in a method call? What about an overloaded method, e.g. method(short[] s) and method(int[] i)? – user207421 Apr 22 '13 at 05:39
  • And I think this is why Java decided against doing this and forced you to just initialize the array with new: simplicity. – Chris Chambers Apr 22 '13 at 05:40
  • @EJP Ah, yes, I see your point now! Thanks all for the answers – One Two Three Apr 22 '13 at 05:49
0

I think whenever we create a variable , the compiler automatically allocates memory to it.The amount of memory created depends upon the type of compiler which you are using.In the first statement you declare an array with the inputs, compiler automatically create space for the array element present in the array but when you declare the array in for loop it create only 2 byte of each run.

For ex.

int x; // create 2 bytes of memory

This space is permanently allocated to int x whether you insert value in this space or not.

int x = "123"; // This code also take 2 bytes of memory and contain value = 123

Similarly,

int a[] ={1,2,3} // create 6 byte of space in memory, 2 byte for each integer variable.

On the other hand when you declare the array in for loop without using the new identifier the compiler assume that it is an int variable and create only 2 bytes of memory space and program gives error.

for (int n : {1, 2, 3}) // create only 2 bytes of memory

So by using the new identifier we allocate a new memory space and insert values which is given in the curly braces.

Sumit Sharma
  • 1,847
  • 1
  • 22
  • 25
-1

To be honest, the only fallacy I see in your explanation is how can you tell a computer to go through an object/memory that does not exist?

You have to create something to let go through it first, here, you have created nothing and the logical fallacy exists in your head because you have thought more deep than the creation rules of Java itself.

Don't worry, I find myself in situations like you but the most important thing is to learn how Java was programmed first!

  • I'm confused by this answer. I also don't see how knowing how Java was programmed should proceed learning any of the syntax or rules behind it. – Makoto Apr 24 '13 at 03:27
  • Are you the one that voted me down? For instance the syntax is given to us by developers, we did not create it. This is what I was trying to say, so unless you haven't developed Java, these type of questions can often be meaningless. And he did not initialse the Java array in the first place. – user2282158 Apr 25 '13 at 03:15
  • The syntax may have not been created by us, but we were given the specifications. And that's something that any reasonable engineer could follow, thus making the question *very* meaningful. – Makoto May 15 '13 at 04:35