You can just create a method that will return the long value of the array length instead of an int.
Example:
public getArrayLength() {
//myArray.length will return an int value, you then add
//the int value to a string and you will get a string of the
//int value. When you parse the int string you will get
//the long value, which is returned
return Long.parseLong((myArray.length) + "");
}
I hope this helps.
Robert
Setting aside the problem of having a data structure requiring gigs and gigs of RAM, you could use a 3- or more- dimensional array to simulate it as you suggest... an 2^21 element array of 2^21 element arrays of 2^21 element array of objects, breaking the long bitwise into 3 regions and applying them to each level of the array.
If the array will mostly be "empty", its elements mostly containing the same default value, your best bet might be some form of "sparse array". Just store an indexed list of individual elements or regions of elements that don't contain the default value.
When you retrieve an element, search the list for the specified index: if it exists, return the element value; otherwise return the default value. When setting a non-default value for an element, add or replace it in the list. If setting a default value, either replace the default value in the list or remove it from the list altogether.
If you actually have this much discrete data, I must agree that a database is your best bet.
Hope this gives you some more ideas.