Hacker News new | past | comments | ask | show | jobs | submit login

> (It’s somewhat counterintuitive that the zero dimension is not the first one in the array.)

I must've read this sentence at least 7 times, but don't understand what this means. Can anyone illuminate?




The article is very confused in general about multidimensional arrays (which are really just arrays of array references in Java). It’s badly written and IMO doesn’t deserve to be on the HN front page.

The author seems to have expectations that Java multidimensional arrays violate, and seems to assume the reader would also have those expectations, but they just seem confused to me.

Except for TFA’s mention of the bytecode instructions and trailing comma, the classic tutorial article is much better: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/ar...


To elaborate further, consider this quote from TFA:

For example,

strangePoints = new int[3][4][0][2]

In this declaration, all dimensions after the zero-size dimension are ignored. So, the result of this declaration is equivalent to a two-dimensional array of ints.

This is just plain wrong. It’s a four-dimensional array of ints, just one that cannot contain more than zero ints, because one of the dimensions is zero.

To illustrate,

    int[][] a = strangePoints[0][0];
will typecheck while

    int b = strangePoints[0][0];
will not (which however it should if the author’s claim that strangePoints is a two-dimensional array of ints was true).

The talk about Object having no size() method and arrays having therefore a length field is also confused. Arrays have distinct types (and classes, in the sense of getClass()), and therefore could very well have a size() method. It’s merely a stylistic choice of Java that they opted for the simpler .length syntax.

The article is so misguided as to be harmful.


Author here. Your "correction" is wrong. All dimensions after the zero dimension are ignored by the JVM. This is explicitly stated in the JVM spec[0].The typecheck you're leaning on is a purely syntactical construct. Inside the JVM, the arrays function and are sized just as I described.

> Object having no size() method and arrays having therefore a length field is also confused. Arrays have distinct types (and classes, in the sense of getClass()), and therefore could very well have a size() method. It’s merely a stylistic choice of Java that they opted for the simpler .length syntax.

What's the "confused" part? Again, my description is accurate and you're simply saying that Java could have chosen a different way to do the same thing, but decided not to.

[0] https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-6.h...


> All dimensions after the zero dimension are ignored by the JVM. This is explicitly stated in the JVM spec[0].

What is stated is: “If any count value is zero, no subsequent dimensions are allocated.” This is mostly just for clarification, because what could the alternative possibly be? It is equivalent to saying that count subarrays are allocated, which when count is zero, of course means that none are allocated. Again, what would the alternative possibly be?

Furthermore, strangePoints.getClass() results in `[[[[I` (so it’s not just syntactical, it’s the actual runtime type), i.e. a four-dimensional array of ints, and not a two-dimensional array of ints as the article claims.

What is true is that what is allocated is a two-dimensional array, but it is an array of empty arrays, not of ints. For example, the expression strangePoints[0][0].length is valid (and yields 0), whereas it wouldn’t be valid for a two-dimensional array of ints. And again that’s on the JVM level, because otherwise the ARRAYLENGTH operation wouldn’t work here. Furthermore, strangePoints[0][0].getClass() of course is valid as well and yields `[[I`, showing that the element type of the two-dimensional array is another two-dimensional array (of ints), and not int.

> What's the "confused" part?

The confused part is this: “Many Java collections have a method called size(), which returns an integer stating the number of elements in the collection. Arrays have no such method. There are several reasons for this, but the principal one is that arrays are simple Object instances—they are not collections. The Object class has no size() method, so arrays don’t either.”

There is no reason why array objects couldn’t have a size() method even though Object doesn’t. Invoking getClass() on an array doesn’t return Object.class, but a subclass of that, and those subclasses could have the additional size() method.

This is also wrong: “Eagle-eyed readers of my earlier statement about length being a field rather than a method call might wonder how a direct subclass of Object would have a field called length to begin with, as Object has no such field.” Arrays don’t have a length field, as calling .getClass().getFields() (or getDeclaredFields()) on an array shows. The .length property is mere syntax, much like .class on an object type. But, again, Java/the JVM could have chosen to imbue array classes with a fully-fledged size() method.


> What is stated is: “If any count value is zero, no subsequent dimensions are allocated.” This is mostly just for clarification, because what could the alternative possibly be?

The key part comes a bit later:

> The components of the last !!allocated!! dimension of the array are initialized to the default initial value (§2.3, §2.4) for the element type of the array type.

Since the last allocated dimension is the one that has zero count... well, that means each component (of which there are none) is initialized to a value of type `int`, so technically speaking, the type of each component (of which there are none) is `int`. Due to the rest of the spec, that means the type of the dimension before that is `int[]`; and that's how you arrive at the conclusion of TFA.

It's quirky, and a semantic argument at best, and certainly not worth fighting over here on HN.


Yeah this was the comment I was coming to look for. I saw a couple sentences that made me go "hmm" but the one that I copied into my clipboard to post about was:

"Arrays, however, have a property called length, which can be queried to get the number of elements in the specified array."

This is not correct and causes bugs. Length is the length of the array, not the number of elements within it. Maybe the author understands this, but precision of language is important here and as-written this is either ambiguous at best or incorrect at worst.

Also the entire section for "Array size and the concept of arrays of arrays" is terribly confused. Again I'm not sure if this is imprecise use of language or if the author is truly this confused about the topic, but:

"As you can see, what you have is truly three arrays, working together to create the equivalent of a three-dimensional array."

No, in the naive case of "new int[M][N][10]" you have 1 + M + MN arrays. And if you are working with only the type int[][][], just checking arr.length, arr[0].length, and arr[0][0].length will not give the the dimensions of the 3d array - any of the arrays can be of any length (the length of the array is not part of the type system).

And I feel like I'm not nitpicking here - note some algorithms, like DP ones for instance, only use a "diagonal" half of a 2d array and allocating the other half would be wasted space. So it's very possible you'll encounter such non-trivially-shaped 2 and 3D arrays in practice.

"Here’s an interesting question: What would happen in a multidimensional array if one of the dimensions were declared with a size of 0? For example,

strangePoints = new int[3][4][0][2]"

This was a TIL to me though, I'm kind of surprised this doesn't throw at runtime? But also, I suppose, not surprised. It's weird because, is int[3][4][0][2] really* an int[][][][]? I guess it's not not an int[][][][] but it's also kind of weird that it is. I guarantee this has caused a bug at some point. This would be a cursed interview question.


Author here. This is simply a comment on the way that Java refers to the subarrays. I believe most developers would think of the first subarray as being referenced with [0], rather than with no index at all. That's all the comment was intended to point out.


I think that it means the definition `int[2][3][4]` is effectively `((int[4])[3])[2]`, *not* `((int[2])[3])[4]`. So it declares an array of 2 (array of 3 (array of 4 ints))`.


It the difference between length and indexing. The new int[0] is providing the 0 as length. Mostly when seeing the construct arr[i] you might think of ‘i’ as the index.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: