Why do we have length of an array as an attribute. array.length
and for String we have a method str.length()
?
Just came in my mind, is there some reason?
Why do we have length of an array as an attribute. array.length
and for String we have a method str.length()
?
Just came in my mind, is there some reason?
A bit simplified you can think of it as arrays being a special case and not ordinary classes (a bit like primitives, but not). String and all the collections are classes, hence the methods to get size, length or similar things.
I guess the reason at the time of the design was performance, if they created it today they had probably come up with something like array backed collection classes instead.
If anyone is interested, here is a small snippet of code to illustrate the difference between the two in generated code, first the source:
public class ArrayTest {
public static void main(String[] args) {
int[] test = {12,1,4};
String test2 = "Hoo";
System.out.println(test.length);
System.out.println(test2.length());
}
}
Cutting a way the not so important part of the byte code, running javap -c on the class results in the following for the two last lines:
20: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
23: aload_1
24: arraylength
25: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
28: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
31: aload_2
32: invokevirtual #5; //Method java/lang/String.length:()I
35: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
In the first case (20-25) the code just ask the JVM for the size of the array (in JNI this would have been a call to GetArrayLength()) whereas in the String case (28-35) it needs to do a method call to get the length.
In the mid 90's, without good JITs and stuff, it would have killed performance totally to only have the java.util.Vector (or something similar) and not a language construct which didn't really behave like a class but was fast. They could of course have masked the property as a method call and handled it in the compiler but I think it would have been even more confusing to have a method on something that isn't a real class.
In Java, an Array stores its length separately from the structure that actually holds the data. When you create an Array, you specify its length, and that becomes a defining attribute of the Array. No matter what you do to an Array of length N (change values, null things out, etc.), it will always be an Array of length N.
A String's length is incidental; it is not an attribute of the String, but a byproduct. Though Java Strings are in fact immutable, if it were possible to change their contents, you could change their length. Knocking off the last character (if it were possible) would lower the length.
I understand this is a fine distinction, and I may get voted down for it, but it's true. If I make an Array of length 4, that length of four is a defining characteristic of the Array, and is true regardless of what is held within. If I make a String that contains "dogs", that String is length 4 because it happens to contain four characters.
I see this as justification for doing one with an attribute and the other with a method. In truth, it may just be an unintentional inconsistency, but it's always made sense to me, and this is always how I've thought about it.
Has been discussed before at CodeRanch.
See the discussion here.
I was taught that for arrays, length is not retrieved through a method due to the following fear: programmers would just assign the length to a local variable before entering a loop (think a for loop where the conditional uses the array's length.) The programmer would supposedly do so to trim down on function calls (and thereby improve performance.) The problem is that the length might change during the loop, and the variable wouldn't.