| Home > Core Java FAQ
> Language Fundamentals FAQ |
| Java
Fundamentals |
| Basic(19) * Constants
and Expressions(40) * Variables and Methods(16)
* Array(11) * Date/Time(36)
* Compile Time(11) * Run
Time(02) * C-vs-Java(12) |
| |
|
Q . Can I allocate an array dynamically?
|
Ans :
Yes
and no; you can create an array with a size determined at run
time, but you cannot change the size of an array once you've
created it.
Arrays
in Java are full-fledged, object citizens of the language. Like
other Java objects, they are created dynamically at run time, and
their storage space is allocated from the virtual machine's system
storage. Because arrays are created at run time, you don't have to
prespecify an array's size at compile time.
There are two ways to create an
array: with an array initializer when declaring an array-type
variable, or with an array creation expression. An array
initializer specifies the complete set of values to be stored in
an array. For example, the following declaration and initializer
create an array holding 5 int values:
int[] myInts = {5, 4, 3, 2, 1}; // int myInts[]... also allowed
A
plain array creation expression, using the new
keyword, creates an array filled with default values for the
element type in the array. You specify the size of the array with
any expression that evaluates to an int. The
following code, for instance, creates an array of sine values; the
array's size is specified by the method's argument:
public static float[] sineArray(int size) {
float[] sineVals = new float[size];
for (int i = 0; i < sineVals.length; ++i) {
sineVals[i] = (float) Math.sin( (i * 2 * Math.PI) / size);
}
return sineVals;
}
Starting
with the JDK 1.1, you can also include an array initializer
directly in an array creation expression. For example:
/* using JDK 1.1: */
// int[] myInts declared elsewhere
myInts = new int[] {5, 4, 3, 2, 1};
Once
a Java array is created, its size is fixed for the lifetime of the
array. If you need more dynamism-an array-like object that can
grow as needed when you use it-consider using the Vector
class in the java.util package.
|
|
Q .
How do I allocate a multidimensional array?
|
Ans
: There are several ways. If you want a rectangular array, you can
allocate the space for the array all at once. The following creates a
4x5 array:
int arr[][] = new int[4][5];
If you want each row to have a different number of columns, you can use the fact that a two-dimensional array is actually an array of arrays.The following code allocates a triangular array:
int arr[][] = new int[4][]; // allocate the four row arrays
for (int i = 0; i < 4; i++) // initialize each of the four rows
arr[i] = new int[i + 1]; // row i has i + 1 columns
Note that if you allocate an array of any kind of object (as opposed to primitive type), all the references will be null by default. These null
references can result in NullPointerExceptions if you try to deference
them. In other words, after doing:
int arr[] = new int[4];
you can say
if (arr[2] == 0)
But after doing
Integer Iarr[] = new Integer[4];
you must fill in the object reference before using it. E.g.,
Iarr[2] = myInt;
or
arr[2] = new Int(27);
before you can say
if (Iarr[2].equals(myInt))
|
|
Q . How do I initialize an array of objects?
|
Ans
:
Write a loop that initializes the
base elements of your array one by one.
In the Java
language, what looks like an array of objects is really an array
of object references— basically, pointers to objects. The
objects themselves are stored separately in space managed by the
Java Virtual Machine. When you create an object-type array, you
are in fact creating an array of object references. Unless you
explicitly initialize the array, moreover, each object reference
receives the default initial value of null. In other
words, creating an object array in Java automatically gives you an
array filled with null object references.
After creating an array, you need to
set each object reference to refer to some bona fide object. The
usual technique for this is to allocate and initialize objects in
a loop through the array, as illustrated:
String[] sArray = new String[10];
for (int i = 0; i < sArray.length; ++i) {
sArray[i] = "string at index " + i;
}
The
behavior of arrays containing objects follows from the fact that
Java array components are in fact nameless variables (The Java
Language Specification, p. 193). These nameless variables are
related to their array in much the same way that (named) instance
variables are related to the class instance containing them. Table
2.7 compares arrays and class instances as two different kinds of
object; you might find this alternate view of Java arrays a
surprising yet useful one.
Table 2.7:
Class versus Array as Two Kinds of Object
Class
instance (obj) |
Array
instance (arr) |
| stores
per-object data in named instance variables |
stores
per-object data in nameless (but numbered) variables |
| can
have variables of different types in one object |
all
variables in object have same type |
accesses
variables by name: obj.fieldName |
accesses
variables by index: arr[index] |
| reference-type
variables hold object references |
[same
as class instance] |
| instance
variables have default initialization |
[same
as class instance |
|
|
Q . How do I copy an array?
|
Ans
: If the array only contains primitive types or if you want to copy
only the object references, not duplicate the objects, then use the
method
java.lang.System.arraycopy(Object src, int src_position,
Object dst, int dst_position, int length);
Otherwise, if you want to duplicate the objects, you have to initialize your new array and write a loop that duplicates each object in the old
array into the new.
Note that the documentation for arraycopy() says that if src and dst refer to the same object, then arraycopy behaves as if the source array
elements are copied into a temporary array (i.e., they are preserved).
Some interpret this as meaning a temporary array will be so allocated,
but that's not Sun's implementation.
|
|
Q . How do I clear an array?
|
Ans : There is no method to clear an array to 0.0, 0, null, false,
'\u0000' etc. When you allocate an array, the elements are set to their
default values, but that doesn't help when you want to reuse an array.
If you want to set the same array to the same set of values many times, create a template array. Fill it with the reset value, then use
System.arraycopy() to copy it into the work array each time you need to
set the work array.
|
|
Q . If arrays are objects, why can't I use a length method to determine an array's size?
|
Ans
:
Such a method would be
reasonable, but it doesn't exist; the Java language designers
decided to expose array length like a public final instance
variable rather than a method.
In Java,
arrays are objects. They are created dynamically from central,
system-managed memory like other objects; they all have Object
as a superclass; and you can invoke any Object method
on them. Given this, it would have been possible to define a length
instance method on arrays to return the length of the array, much
like the length method in class String.
However, the Java language designers
chose to represent length simply as an instance
variable of the array. The length variable is always
accessible but never changeable; its value is fixed at the time
the array is created.
|
|
Q . Why can't I do myArray.length() ? Arrays are just objects, right?
|
Ans
: Yes, the Java specification says that arrays are object references
[JLS 10.2] just like classes are. However, arrays cannot contain methods. Instead you have to use myArray.length, which is a data item
(not a method) called "length", belonging to myArray.
|
|
Q .
NullPointerExceptions with arrays of objects?
|
Ans
: When you allocate an array of objects, each component of the array is initialized to null. The
individual components of the array must still be initialized with a constructor or an assignment
statement. For example, consider this statement:
Integer[] scores = new Integer[10];
int m = scores[5].intValue(); // throws NullPointerException
This creates an array called scores containing ten references to Integer objects. Then it tries to get the value of the fifth component. However, each of those references is initially set to null. Thus when you try to call a method on one of the components of the array or pass the component to a method that expects a non-null argument, a NullPointerException is thrown.
To fix this, you need to initialize the components of the array, either with constructors or with assignment statements For example:
Integer[] scores = new Integer[10];
for (int i = 0; i < scores.length; i++) scores[i] = new Integer(i);
int m = scores[5].intValue();
You do not need to initialize all the components of the array though it's a good idea to do so. You can initialize just those you'll use, or you can make sure you catch and handle NullPointerExceptions in the appropriate places.
This is different from how Java handles uninitialized non-array reference variables. By way of contrast when you write,
Integer score;
int m = score.intValue();
the compiler catches the null reference in score and complains. You have to fix the problem before you can compile the program. However in general the compiler has no way to know whether an array component has or has not been initialized. Therefore the check for the non-nullness of an array component is deferred till runtime when the NullPointerException may be thrown.
|
|
Q . What is a fast way to set all elements of an array?
|
Ans
: Using a loop that does it one by one is probably 20 to 40 times
slower than good old memset() in C.
A fast way on many VM's is to set the first byte of the array, then use
System.arraycopy() repeatedly to fill the next byte, the next two bytes, the next four bytes, the next eight bytes, etc., and when you
get past halfway, fill in the rest.
public static void bytefill(byte[] array, byte value) {
int len = array.length;
if (len > 0)
array[0] = value;
for (int i = 1; i < len; i += i)
System.arraycopy( array, 0, array,
i, ((len - i) < i) ? (len - i) : i);
} This is faster on Sun's VM than a simple loop, and probably even faster
under JITs because it only performs at most log2(array.length) bounds
checks. This is a clever code idiom applying the binary chop algorithm
to arrays even when their size is not a power of 2.
|
|
Q . When I change a field in just one object in my array, that field changes in all the objects in my array?
|
Ans
: Here the problem is probably that you have initialized the array
with N references to the same one object.
This is easy to overlook, because arrays in Java only contain references to objects, not objects. (Or they can contain primitives).
|
|
Q .
How do you deallocate an array in Java?
|
Ans
: Java uses automatic garbage collection and does not support C++'s delete or delete[]. If the last reference to an object is removed, the object will be garbage collected. If the variable referring to an array becomes out of scope, its reference is lost. (Note that an array is an object in Java). Or you can assign null to the variable directly.
|
|
|
|