aspose file tools*
The moose likes Beginning Java and the fly likes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark ""empty" array declarations" Watch ""empty" array declarations" New topic
Author

"empty" array declarations

Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Hello,
I am curious about what's probably a design consideration made when designing the Java language. When considering these possible attempts at array declarations:

I have difficulty determining a comprehensive explanation for why each of these declarations are either allowed or not allowed. The trouble maker for me is the third example.
Rather than tripping over my own explanations (i.e. guesses), hopefully someone else could shed some light on this subject.
Thank You.
Ivor Horton
Author
Ranch Hand

Joined: Mar 22, 2002
Posts: 67
int[] numbers1 = new int[0]; // compiles
This works but is not very useful. The variable numbers1 references an array of type int[] that has no elements, so you can't store any data in it.
int[] numbers2 = new int[]; // won't compile
This is not a legal statement. You must specify the number of elements that are to be allocated for the array.
int[][] numbers3 = new int[0][]; // compiles
This is legal but not useful. After executing this, numbers3 will contain a reference to an array of type int[][] that has no elements.
An array of type int[][] is essentially an array of 1-dimensional arrays. The first index accesses a particular 1-dimensional array and the second index identifies an element within that array. A more useful statement of this type would be:
int[][] numbers3 = new int[5][];
After executing this numbers3 will contain a reference to an array of type int[][] with five elements. Each element of this array contains null, but could be assigned a reference to an array of type int[]. We could therefore write:
numbers3[0] = new int[4];
numbers3[1] = new int[6];
numbers3[2] = new int[8];
numbers3[3] = new int[10];
numbers3[0] = new int[12];

int[][] numbers4 = new int[][]; // won't compile
This is illegal because the dimensions are not specified. You must at least define the first dimension as in the previous example.
int[][] numbers5 = new int[][0]; // won't compile
This is illegal because you have only specified the second dimension. The first dimension defines the number of references to 1-dimensional arrays that are to be stored and the second dimension defines the number of elements in each of these. You cannot specify the second dimension without specifying the first.(You can do the reverse tho' )


Ivor Horton<br />Author of the Beginning Java Series including the new <a href="http://www.amazon.com/exec/obidos/ASIN/1861005695/ref=ase_electricporkchop" target="_blank" rel="nofollow">Beginning Java 2 SDK 1.4 Edition</a>
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by Ivor Horton:
int[] numbers1 = new int[0]; // compiles
This works but is not very useful. The variable numbers1 references an array of type int[] that has no elements, so you can't store any data in it.

I used to wonder why, when Java was created, there was a decision made to allow arrays of 0 length. As it turns out, they can be useful at times. Imagine you have a method that, as one of it's parameters, takes an array. Even if you don't have any data to put in that array, you're still obliged to pass something in its place or the compiler will complain. You might be able to pass null instead, but that could cause a NullPointerException, depending upon how that method was implemented.
Here's a quick example:

Granted, I think most things could be just as well done without arrays of length 0, but they can be useful from time to time.
Corey
[ March 26, 2002: Message edited by: Corey McGlone ]

SCJP Tipline, etc.
Ivor Horton
Author
Ranch Hand

Joined: Mar 22, 2002
Posts: 67
You have a valid point Corey. You can certainly pass an array of zero length to a method. It's a good idea to check for a null argument though. Even if you allow for zero-length arrays, you can still have null passed to a method
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by Ivor Horton:
You have a valid point Corey. You can certainly pass an array of zero length to a method. It's a good idea to check for a null argument though. Even if you allow for zero-length arrays, you can still have null passed to a method

Indeed, I think you should. In the standard class libraries, (let's use the method Class.getConstructor(Class[]) as an example) you are allowed to pass a null argument to mean the same thing as an array of 0 length.
Unfortunately, had this not been checked for, we'd have no way to change the code of java.lang.Class and we'd be required to pass an array of length 0.
I honestly think what was done in java.lang.Class was the right thing to do, but, not all code is developed by expert programmers and, sometimes, we don't have access to modify the methods we're invoking. If the code there is bad, we'll just have to deal with it.
Corey
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Thank you for the replies.
I'd like to phrase my question better, though. Does anybody have a good explanation of the thinking behind:
Originally posted by Ivor Horton:
You must at least define the first dimension as in the previous example.
You cannot specify the second dimension without specifying the first.(You can do the reverse tho')

when Java was designed?
Matthew Haynes
Greenhorn

Joined: Feb 04, 2002
Posts: 6
The second dimension is relating to the arrays defined in the first dimension. So if you don't define the first array, Java does not know what to apply the second dimension to.
Example
int[][] numbers3 = new int[5][];
Java knows that there are five number arrays (but at this point is doesn't know their size).
int[][] numbers3 = new int[][5];
You are trying to tell Java that an unkown number of arrays should have a size of 5. Where should it store this information?
Regards,
Matt
Ivor Horton
Author
Ranch Hand

Joined: Mar 22, 2002
Posts: 67
Dirk,
Matthew's explanation is pretty good. You can also think of it in terms of how memory is conceptually allocated. If you write:
int[][] numbers = null;
This essentially allocates one memory location to store a reference to a two dimensional array of type int[][] and it contains null.
If we write:
int[][] numbers = new int[5][];
This allocates one memory location as in the previous example, but here it contains a reference to an array of type int[][]. This array is 1-dimensional array of references to arrays of type int[] and it has 5 elements containing null. Now we have one location storing a reference, plus an array of five locations containing null.
If we write:
int[][] numbers = int[5][6];
We get the same as the previous example plus five arrays of type int[], each with six elements. Now each element in the array of 5 references contains a reference to one of the 1-dimensional arrays with 6 elements.
It is actually slightly more complicated than this as arrays in Java are objects, but in principle it works as described.
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
I seem to have failed to fully describe what I am curious about. Please, let me take another stab at what I'm curious about...
If an array is declared like so:
int[][] numbers = new int[2][];
this creates a two-dimensional array with two components - both of which are null. Either component could be changed:
numbers[0] = new int[] {4, 5, 6, 7, 8, 9, 0};
numbers[1] = new int[] {1, 2, 3};
and new memory would be allocated for the new objects. What is the compelling reasoning behind not being able to do this very same thing, and using similar language (grammar) with a one-dimension array?
int[] numbers = new int[];
Now, numbers would be null.
numbers = new int[] {1, 2, 3};
Now, new memory would be allocated for the new object. But, of course, this doesn't compile. It seems to me to be inconsistent.
Thank You.
Ivor Horton
Author
Ranch Hand

Joined: Mar 22, 2002
Posts: 67
Dirk,
It can't work the way you are looking for because of the way things are stored. Take a one-dimensional array:
int[] array = new int[5];
The variable array stores a single reference - this is the address where the array of five integers is stored. The location of the array storing the integers MUST be recorded somewhere as it can't just float around. With a one-dimensional array, the address of the array is stored in the variable, array.
Now consider a two-dimensional array:
int[][] numbers = new int[5][6];
The variable numbers stores the address of an array of five elements. Each element in this array stores the address of an array of six integers. If we did not specify the dimension 5, for the first dimension, how many arrays of six integers should there be? And where would their addresses be stored?
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Well, forgive my being obstinate, but I must not be asking the question clearly enough (or I'm failing to put the pieces together)...
Why, is declaring an array like this:
int[] numbers = null;
versus declaring an array like this:
int[] numbers = new int[];
(which is not allowed), conceptually different than declaring a two dimesional array like this:
int[][] numbers = {null, null};
versus like this:
int[][] numbers = new int[2][];
(which is allowed)? In the cases of the single dimension array declaration and the two dimensional array declarations, all declare arrays with components that are null. Not being able to use all of the above styles would seem to me to be an inconsistent grammar in Java. Perhaps it isn't and I'm curious about what is going on with regards to memory allocation (or any other related concern) that this is not an inconsistent grammar in Java?
Thank You.
[ March 28, 2002: Message edited by: Dirk Schreckmann ]
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
Originally posted by Ivor Horton:
Now consider a two-dimensional array:
int[][] numbers = new int[5][6];
If we did not specify the dimension 5, for the first dimension, how many arrays of six integers should there be? And where would their addresses be stored?

But the question I am asking is, if we did not specify the second dimension, why does Java know where to store the references to null and why doesn't this system of knowledge carry over to a one dimensional array without the size of the first (and only) dimension specified? Why isn't a reference to null created as it would be with a the two dimesional array declared without the size of the second dimension specified?
Thank you for your time.
Ivor Horton
Author
Ranch Hand

Joined: Mar 22, 2002
Posts: 67
I'm not sure what you would expect your statement:
int[] numbers = new int[];
to mean. Since there is no dimension specified for the array on the RHS, the array cannot be defined. What space should be allocated with this form and what should be stored in it.
Braces are used to enclose a set of values to be stored in an array and to define the dimensions of the array, so your statement:
int[][] numbers = {null, null};
implies you are defining a two-dimensional array based on a one-dimensional set of two elements with the value null. The values between the braces are inconsistent with the type of element to be stored in the array - type int. The dimensionality of the data values(1-dimensional) is inconsistent with the dimensionality of the array type(2-dimensional).
Of course, you can write:
int[][] numbers = {{1,2}, {3,4},{5,6}};
Dirk Schreckmann
Sheriff

Joined: Dec 10, 2001
Posts: 7023
I'm not sure what you would expect your statement:
int[] numbers = new int[];
to mean. Since there is no dimension specified for the array on the RHS, the array cannot be defined. What space should be allocated with this form and what should be stored in it.

I would expect this style of array declaration to declare that the identifier numbers would be able to refer to a single dimension array, but it now refers to null. I would expect that no space would be allocated for an object - excepting whatever space is allocated for a null reference.

Braces are used to enclose a set of values to be stored in an array and to define the dimensions of the array, so your statement:
int[][] numbers = {null, null};
implies you are defining a two-dimensional array based on a one-dimensional set of two elements with the value null. The values between the braces are inconsistent with the type of element to be stored in the array - type int. The dimensionality of the data values(1-dimensional) is inconsistent with the dimensionality of the array type(2-dimensional).

I'd argue that this is not an entirely correct set of statements. The values between the braces are not inconsistent with the type of element to be stored in the array any more so than an identifier, that could refer to a single dimension array, refers to null. This is allowed:
int[][] numbers = {null, null};
and declares that the identifier numbers refers to a two dimensional array with two components. These components are null right now, and later can be changed like this:
numbers[0] = new int[] {1, 2, 3};
numbers[1] = new int[] {4, 5, 6, 7, 8};
So, when you said:
[qb]
The values between the braces are inconsistent with the type of element to be stored in the array - type int.
[QB]

you were wrong. In the first dimension, the components to be stored in the array are themselves single dimension arrays - not type int.
Again, thank you for your time.
 
Consider Paul's rocket mass heater.
 
subject: "empty" array declarations