Initialized HashSet Array in Java - java

I'm having a problem initializing array of HashSet
int N = 100;
HashSet<Integer> []array = new HashSet[N];
for (HashSet<Integer> set:array){
set = new HashSet<Integer>();
}
But the array contains only null. (Also error when HashSet []array = .... )
But when running with:
for(int i = 0; i < N; i++){
array[i] = new HashSet<Integer>();
}
All is well.
Why does the first code isn't working? Is it my mistake?
Thank you

You never actually assign initialized instances to elements of the array. Instead you iterate over the elements of the array with a variable that gets assigned to a new object in your loop, then is never used. In a case like this the enhanced for...each syntax is not appropriate, use the traditional for loop instead.

two 'for' is different in Java, look the java code & bytecode ..
Example:
public class T{
public static void main(String[] args){
String[] data = new String[10];
System.out.print("");
for(String str:data){
str="1";
}
System.out.print("");
for(int i=0;i<data.length;i++){
data[i]="1";
}
}
}
$>javac -classpath . T.java
$>javap -c T
Compiled from "T.java"
public class T extends java.lang.Object{
public T();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10
2: anewarray #2; //class java/lang/String
5: astore_1
6: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #4; //String
11: invokevirtual #5; //Method java/io/PrintStream.print:(Ljava/lang/String;)V
14: aload_1
15: astore_2
16: aload_2
17: arraylength
18: istore_3
19: iconst_0
20: istore 4
22: iload 4
24: iload_3
25: if_icmpge 44
28: aload_2
29: iload 4
31: aaload
32: astore 5
34: ldc #6; //String 1
36: astore 5
38: iinc 4, 1
41: goto 22
44: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
47: ldc #4; //String
49: invokevirtual #5; //Method java/io/PrintStream.print:(Ljava/lang/String;)V
52: iconst_0
53: istore_2
54: iload_2
55: aload_1
56: arraylength
57: if_icmpge 71
60: aload_1
61: iload_2
62: ldc #6; //String 1
64: aastore
65: iinc 2, 1
68: goto 54
71: return
}
from line 25--44 and line 57--71:
aload : Retrieves an object reference from a local variable and pushes it onto the operand stack.
aaload : Retrieves an object reference from an array of objects and places it on the stack.
astore : Take object or reference store to local variable.
aastore : Take reference type value store to array.
so,first can't store array , didn't using initializing array.

An enhanced for loop, does not use the actual instances in the array( and as well, collection), but rather copies them in the loop control variable.
This should not be a problem with non-null values, since they point to the same object. Problems arise, if the values are null, and re-assigning values to the control variable, would not change the actual value. So in this case, always use regular for loops.
The same would be true, to arrays of primitive types, since coping them, and changing the copied variable, will not affect the original variable.

Simply use new Set[n] instead of new HashSet[n] , to get it working
Set<Integer>[] list = new Set[n];
for(int i=0;i<n;i++)
list[i] = new HashSet<>();

You need to create an array that contains HashSet
so, you need to initialize the array and then initialize the HashSet
which I have provided in the below code
int N = 100;
Set<Integer>[] array = new Set[n];
for(int i = 0; i < n; i++) {
array[i] = new HashSet<Integer>();
}

Related

Is the argument of append in StringBuilder a new String object and will it be garbage collected?

In the following code, When it reaches the comment, if the GC is not run, approximately 1000 object is created(according to OCA book), the StringBuilder is modified and remains as one object, the empty string " " is pooled and re-used, that's all that is explained. isn't the argument s a new String("s") that needs to be GCed, and i , will it not be converted to a new String object first, then combined with " " creates another new String object making them 2 String objects at that line, eligible for GC along with the append's argument, a total of 3 String object in every loop. so a sum of 3000 object when the code reaches the comment line?
public class Mounds {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String s = new String();
for (int i = 0; i < 1000; i++) {
s = " " + i;
sb.append(s);
}
// done with loop
}
}
If we compile this code and look at the generated bytecode we can examine that exactly
public static void main(java.lang.String[]) throws java.io.IOException;
Code:
0: new #19 // class java/lang/StringBuilder
3: dup
4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: new #22 // class java/lang/String
11: dup
12: invokespecial #24 // Method java/lang/String."<init>":()V
15: astore_2
16: iconst_0
17: istore_3
18: goto 47
21: new #19 // class java/lang/StringBuilder
24: dup
25: ldc #25 // String
27: invokespecial #27 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
30: iload_3
31: invokevirtual #30 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: astore_2
38: aload_1
39: aload_2
40: invokevirtual #38 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: pop
44: iinc 3, 1
47: iload_3
48: sipush 1000
51: if_icmplt 21
54: return
The instructions we care about are from 21 to 40. In 21, there is a second StringBuilder created, we will come back to that later.
In 25 We see, that there is a ldc, which means that a literal is pushed to the stack, in this case it is the literal String " ".
Then the real magic happens. The constructor of the second StringBuilder is called, which takes the literal from the stack as argument. Then the int i is loaded from the local variable array with iload_3, after that the append method of the second StringBuilder is called to append that i to it, and then the toString is called. With astore_2 and aload_1 the return value of the toString call is stored, and the first StringBuilder is loaded, and after that the String is loaded again. And finally the append method of the first StringBuilder is called to add that new String to the StringBuilder.
So it turns out, that ther is a new StringBuilder created in every loop, because everytime you use " " + i a StringBuilder has to be created to concatenate the String and int. Additionally a new String will be created by the toString method of the intermediate StringBuilder, so there will be a total of 2000 Objects there.
A better version would look like this:
for (int i = 0; i < 1000; i++) {
sb.append(' ');
sb.append(i);
}
That will create the following bytecode:
public static void main(java.lang.String[]) throws java.io.IOException;
Code:
0: new #19 // class java/lang/StringBuilder
3: dup
4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: new #22 // class java/lang/String
11: dup
12: invokespecial #24 // Method java/lang/String."<init>":()V
15: astore_2
16: iconst_0
17: istore_3
18: goto 37
21: aload_1
22: bipush 32
24: invokevirtual #25 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
27: pop
28: aload_1
29: iload_3
30: invokevirtual #29 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
33: pop
34: iinc 3, 1
37: iload_3
38: sipush 1000
41: if_icmplt 21
44: return
We can see, that there now is only one StringBuilder, which gets its append method called twice, so no memory is allocated here and this should be better.
The optimal usage would be:
StringBuilder sb = new StringBuilder(4000);
for (int i = 0; i < 1000; ++i) {
sb.append(' ').append(i);
}
... do something with sb.toString()
As:
String s = new String(); creates an unnecessary empty string. Same as String s = "";. (Optimization not considered.)
s = " " + i; concatenates two strings into a new String. A task one should leave to the StringBuilder, as that is the sole purpose of it.
Appending a char ' ' is more efficient than a String " ".
new StringBuilder(4000) with an initial capacity one could use here, preventing intermittent reallocation on appending. 1000 numbers of which 900 are 3 digits, plus a space, will fit in 4000 chars.
the compiler probably realises that the scope of variable s is inside the loop so it inlines the assignment into the append() to produce
sb.append(" " + i)
so now only the conversion of the int creates a new String in each iteration.

Why jdk code style uses a variable assignment and read on the same line - eg. (i=2) < max

I noticed that in the jdk source code and more specifically in the collections framework there is a preference in assigning variables right before reading them in expressions. Is it just a simple preference or is it something more important which I am not aware of? One reason that I can think of is that the variable is used in this expression only.
As I am not used to this style I find it hard to read it. The code is very condensed. Below you can see an example taken from java.util.HashMap.getNode()
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 && ...) {
...
}
As already mentioned in the comment: Doug Lea, who is one of the main authors of the collections framework and the concurrency packages, tends to do optimizations that may look confusing (or even counterintuitive) for mere mortals.
A "famous" example here is copying fields to local variables in order to minimize the size of the bytecode, which is actually also done with the table field and the local tab variable in the example that you referred to!
For very simple tests, it does not seem to make a difference (referring to the resulting bytecode size) whether the accesses are "inlined" or not. So I tried to create an example that roughly resembles the structures of the getNode method that you mentioned: An access to a field that is an array, a length check, an access to a field of one array element...
The testSeparate method does separate assignments and checks
The testInlined method uses the assignment-in-if-style
The testRepeated method (as a counterexample) does every access repeatedly
The code:
class Node
{
int k;
int j;
}
public class AssignAndUseTestComplex
{
public static void main(String[] args)
{
AssignAndUseTestComplex t = new AssignAndUseTestComplex();
t.testSeparate(1);
t.testInlined(1);
t.testRepeated(1);
}
private Node table[] = new Node[] { new Node() };
int testSeparate(int value)
{
Node[] tab = table;
if (tab != null)
{
int n = tab.length;
if (n > 0)
{
Node first = tab[(n-1)];
if (first != null)
{
return first.k+first.j;
}
}
}
return 0;
}
int testInlined(int value)
{
Node[] tab; Node first, e; int n;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1)]) != null) {
return first.k+first.j;
}
return 0;
}
int testRepeated(int value)
{
if (table != null)
{
if (table.length > 0)
{
if (table[(table.length-1)] != null)
{
return table[(table.length-1)].k+table[(table.length-1)].j;
}
}
}
return 0;
}
}
And the resulting bytecodes: The testSeparate method uses 41 instructions:
int testSeparate(int);
Code:
0: aload_0
1: getfield #15 // Field table:[Lstackoverflow/Node;
4: astore_2
5: aload_2
6: ifnull 40
9: aload_2
10: arraylength
11: istore_3
12: iload_3
13: ifle 40
16: aload_2
17: iload_3
18: iconst_1
19: isub
20: aaload
21: astore 4
23: aload 4
25: ifnull 40
28: aload 4
30: getfield #37 // Field stackoverflow/Node.k:I
33: aload 4
35: getfield #41 // Field stackoverflow/Node.j:I
38: iadd
39: ireturn
40: iconst_0
41: ireturn
The testInlined method indeed is a tad smaller, with 39 instructions
int testInlined(int);
Code:
0: aload_0
1: getfield #15 // Field table:[Lstackoverflow/Node;
4: dup
5: astore_2
6: ifnull 38
9: aload_2
10: arraylength
11: dup
12: istore 5
14: ifle 38
17: aload_2
18: iload 5
20: iconst_1
21: isub
22: aaload
23: dup
24: astore_3
25: ifnull 38
28: aload_3
29: getfield #37 // Field stackoverflow/Node.k:I
32: aload_3
33: getfield #41 // Field stackoverflow/Node.j:I
36: iadd
37: ireturn
38: iconst_0
39: ireturn
Finally, the testRepeated method uses a whopping 63 instructions
int testRepeated(int);
Code:
0: aload_0
1: getfield #15 // Field table:[Lstackoverflow/Node;
4: ifnull 62
7: aload_0
8: getfield #15 // Field table:[Lstackoverflow/Node;
11: arraylength
12: ifle 62
15: aload_0
16: getfield #15 // Field table:[Lstackoverflow/Node;
19: aload_0
20: getfield #15 // Field table:[Lstackoverflow/Node;
23: arraylength
24: iconst_1
25: isub
26: aaload
27: ifnull 62
30: aload_0
31: getfield #15 // Field table:[Lstackoverflow/Node;
34: aload_0
35: getfield #15 // Field table:[Lstackoverflow/Node;
38: arraylength
39: iconst_1
40: isub
41: aaload
42: getfield #37 // Field stackoverflow/Node.k:I
45: aload_0
46: getfield #15 // Field table:[Lstackoverflow/Node;
49: aload_0
50: getfield #15 // Field table:[Lstackoverflow/Node;
53: arraylength
54: iconst_1
55: isub
56: aaload
57: getfield #41 // Field stackoverflow/Node.j:I
60: iadd
61: ireturn
62: iconst_0
63: ireturn
So it seems that this "obscure" way of writing the queries and assignments can, indeed, save a few bytes of bytecode, and (given the justification in the linked answer about storing fields in local variables) this may have been the reason to use this style.
But...
in any case: After the method has been executed a few times, the JIT will kick in, and the resulting machine code will have "nothing" to do with the original bytecode - and I'm pretty sure that all three versions will actually be compiled to the same machine code in the end.
So the bottom line is: Don't use this style. Instead, just write dumb code that is easy to read and maintain. You'll know when it's your turn to use "optimizations" like these.
EDIT: A short addendum...
I have made a further test, and compared the testSeparate and testInlined method concerning the actual machine code that is generated by the JIT.
I modified the main method a bit, to prevent unrealistic over-optimizations or other shortcuts that the JIT might take, but the actual methods have been left unmodified.
And as expected: When calling the methods a few thousand times with a hotspot disassembly JVM and -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:+PrintAssembly, then the actual machine code of both methods is identical.
So once more, the JIT does its job pretty well, and the programmer can focus on writing readable code (whatever that means).
... and and a minor correction/clarification:
I did not test the third method, testRepeated, because it is not equivalent to the other methods (and thus, it can not result in the same machine code). This is, by the way, another small advantage of the strategy of storing fields in local variables: It offers a (very limited, but sometimes handy) form of "thread safety": It is made sure that the length of an array (like the tab array in the getNode method of HashMap) can not change while the method is being executed.

Operation inside when we add two Integer objects?

Can some one explain me how the internal behavior when we add two Integer objects in java? (like it is unbox Object into primitives and then add two integers and finally boxed it in to Integer object)
Integer sum = new Integer(2) + new Integer(4);
It's compiled into this:
Integer sum = Integer.valueOf(new Integer(2).intValue()+new Integer(4).intValue());
You can verify this by looking at the byte code disassembly obtained with javap -c.
Here is the part that corresponds to new Integer(2).intValue(), leaving int 2 on the stack:
0: new #2; //class java/lang/Integer
3: dup
4: iconst_2
5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
8: invokevirtual #4; //Method java/lang/Integer.intValue:()I
Here is the part that corresponds to new Integer(4).intValue(), leaving int 4 on the stack:
11: new #2; //class java/lang/Integer
14: dup
15: iconst_4
16: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
19: invokevirtual #4; //Method java/lang/Integer.intValue:()I
And here the sum 2+4 is calculated with iadd, the sum is boxed into an Integer by a call to Integer.valueOf, and the result is stored in the first local variable (astore_1):
22: iadd
23: invokestatic #5; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
26: astore_1
creation of two Integer instances.
Auto-unboxing of those two instances.
new int that holds the result.
Auto-boxing the result into Integer sum instance.

Java: what is faster split in a loop or doing it before [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Goolge comes up with a lot of comparisions but not on what I am looking for:
What is better if I want to iterate through a splitted String
String[] flagArr = flags.split(";");
for (String f: flagArr) {
// some stuff
}
OR
for (String f: flags.split(";")) {
// some stuff
}
With the second pice of code I wonder if the compiler is smart enough to do the split only once
You can check the generated bytecode, but I'm pretty sure they'll both do the same thing. Why would the second one be any different?
EDIT: As you can see, both ways only call split() once.
The bytecode for the first one:
public class javatesting.JavaTesting extends java.lang.Object{
public javatesting.JavaTesting();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String 1;2;3
2: astore_1
3: aload_1
4: ldc #3; //String ;
6: invokevirtual #4; //Method java/lang/String.split:(Ljava/lang/String;)
[Ljava/lang/String;
9: astore_2
10: aload_2
11: astore_3
12: aload_3
13: arraylength
14: istore 4
16: iconst_0
17: istore 5
19: iload 5
21: iload 4
23: if_icmpge 41
26: aload_3
27: iload 5
29: aaload
30: astore 6
32: aconst_null
33: astore 6
35: iinc 5, 1
38: goto 19
41: return
}
And the bytecode for the second one:
public class javatesting.JavaTesting extends java.lang.Object{
public javatesting.JavaTesting();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String 1;2;3
2: astore_1
3: aload_1
4: ldc #3; //String ;
6: invokevirtual #4; //Method java/lang/String.split:(Ljava/lang/String;)
[Ljava/lang/String;
9: astore_2
10: aload_2
11: arraylength
12: istore_3
13: iconst_0
14: istore 4
16: iload 4
18: iload_3
19: if_icmpge 37
22: aload_2
23: iload 4
25: aaload
26: astore 5
28: aconst_null
29: astore 5
31: iinc 4, 1
34: goto 16
37: return
}
It doesn't matter at all. Don't waste time with such type of optimization.
EDIT: If you ever want to care about such thing than you might use the second option since the array with the splits will exist only inside the for loop scope.
If you really want to see the difference in bytecode, use javap -c. Compiled with the Eclipse compiler, the first version (with a local variable in the source code) gives this:
public static void test(java.lang.String);
Code:
0: aload_0
1: ldc #16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: astore_1
7: aload_1
8: dup
9: astore 5
11: arraylength
12: istore 4
14: iconst_0
15: istore_3
16: goto 27
19: aload 5
21: iload_3
22: aaload
23: astore_2
24: iinc 3, 1
27: iload_3
28: iload 4
30: if_icmplt 19
33: return
}
And the second:
public static void test(java.lang.String);
Code:
0: aload_0
1: ldc #16; //String ;
3: invokevirtual #18; //Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
6: dup
7: astore 4
9: arraylength
10: istore_3
11: iconst_0
12: istore_2
13: goto 24
16: aload 4
18: iload_2
19: aaload
20: astore_1
21: iinc 2, 1
24: iload_2
25: iload_3
26: if_icmplt 16
29: return
}
As you can see (if you can read this), the first variant does use an extra local variable slot (astore_1/aload_1 at the beginning). However (a) even if the bytecode was interpreted, the overhead of this would be negligible (it's just copying the reference) and (b) any JIT compiler will be able to optimize this, whether you have done some static bytecode optimization beforehand or not: local variable (1) is never subsequently used.
Local variables in the source code are mainly used for clarity, and for being able to re-use intermediate results. Fundamentally, the second variant (without an explicit local variable) will not let you re-use the result of split further down in your method (or even directly within the loop), whereas you could when naming your local variable in the code.
With the second pice of code I wonder if the compiler is smart enough
to do the split only once
The only difference between your two methods is the explicit declaration of a local variable in the source code.
In both cases, for (String f: flags.split(";")) { } is syntactic sugar (except that neither local variables are accessible) equivalent to :
int _hidden_i = 0;
for (String[] _hidden_arr=flags.split(";"); _hidden_i<_hidden_arr.length; _hidden_i++){
String f = _hidden_arr[_hidden_i];
// some stuff
}
The points to note are that:
With this notation, _hidden_i is never exposed, so you can never allocate something into _hidden_arr[_hidden_i].
Even a naive source-to-bytecode compiler knows that both _hidden_arr and _hidden_i will never be used again, so it doesn't copy them for further use.
What would have been fundamentally different would have been:
for (var i = 0; i < flags.split(";").length; i++) {
String f = flags.split(";")[i];
}
In the for(;;) notation, the first part is always executed once. The second expression is always executed before entering the loop block (to test whether or not to run it). The last is always executing after running the loop block (unless break is used).
You would generally want to avoid method calls that are potentially heavy in the second part, especially when it's always going to be the same result.
I think the compiler will optimize that. It might depend on the Java provider you hae chosen (sun, ibm, etc...) but this is so simple I would be surprised if every compiler did not.
Perhaps create a really large flags string and do some simple performance testing?
But, since this is easy, why not just do your first option....
I'm quite certain the the split will be done only one. Internally this code will be translated into a loop with an iterator, so the compiler will do the split once, create the resulting collection, then create the iterator over that collection.
The iterator would not be pointing to the right place if the split were to be repeated.
Try this:
public double calculateRunTime()
{
long startTime = System.currentTimeMillis();
split();
long endTime = System.currentTimeMillis();
return endTime - startTime;
}

How Does Java Know How to Iterate an Array

String[] strs = new String[] { "1", "2", ... , "6" };
for (String s : strs) {
System.out.println(s);
}
This is a question about java internals.
In the above code sample, how does the foreach loop figure out how long the array is? Are arrays actually objects internally or is it using stuff like sizeof that is inaccessible to front end programmers?
I have a feeling I'm just missing something stupid, but I figure it could also be cool. :-)
I compiled the following code:
public class ArrayIterator
{
public static void main(String[] argv)
{
String[] strs = new String[] { "1", "2", "3", "4", "5" };
enhancedPrint(strs);
normalPrint(strs);
}
public static void enhancedPrint( String[] strs )
{
for (String s : strs)
{
System.out.println(s);
}
}
public static void normalPrint( String[] strs )
{
String[] localArray = strs;
int len = localArray.length;
for (int i = 0; i < len; i++)
{
String s = localArray[i];
System.out.println(s);
}
}
}
This is the disassembled (javap -c ArrayIterator) bytecode for the iterating functions:
The enhanced print:
public static void enhancedPrint(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
A normal for loop:
public static void normalPrint(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
As you can see, in both cases, the compiler is loading the arrays length (strs.length) and looping against it. We see that the enhanced for-each loop, in the case of an Array is syntactic sugar for looping against the array's length (rather than in an Object's case where it uses an Iterator).
I have edited the 'normal' for loop such that it is much less idiomatic, but that it has the same bytecode as the enhanced for loop. For all intents and purposes, the normal for loop version is what the compiler generates when it compiles the enhanced for each loop.
Yes, there is something akin to the C++ sizeof operator -- it's the length instance variable (which gives the number of elements in the array, not the size in bytes.) The length field is always a public member of the array, so it is accessible to Java programmers.
And yes, arrays are objects, and not just internally.
(More broadly, the for loop syntax works as described in the question that org.life.java linked to; but that isn't quite what you were asking.)
Yes, arrays are objects with a "length" field. Java Language Specification: http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#64347

Categories

Resources