Java中的长度和长度()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1965500/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
length and length() in Java
提问by Nitish Upreti
Why do we have the length of an array as an attribute, array.length
, and for String we have a method, str.length()
?
为什么我们有一个数组的长度作为属性array.length
,而对于 String 我们有一个方法,str.length()
?
Is there some reason?
有什么原因吗?
回答by Fredrik
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 LengthTest {
public static void main(String[] args) {
int[] array = {12,1,4};
String string = "Hoo";
System.out.println(array.length);
System.out.println(string.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:
切开字节码中不那么重要的部分,javap -c
在类上运行会导致最后两行的结果如下:
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 asks 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.
在第一种情况 (20-25) 中,代码只向 JVM 询问数组的大小(在 JNI 中,这将是对 GetArrayLength() 的调用),而在 String 情况下 (28-35),它需要执行方法调用以获取长度。
In the mid 1990s, 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.
在 1990 年代中期,如果没有好的 JIT 和其他东西,如果只有 java.util.Vector(或类似的东西)而不是一个真正表现得不像类但速度很快的语言结构,它会完全降低性能。他们当然可以将属性屏蔽为方法调用并在编译器中处理它,但我认为在不是真正类的东西上使用方法会更加混乱。
回答by jakeboxer
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.
在 Java 中,数组将其长度与实际保存数据的结构分开存储。当你创建一个数组时,你指定它的长度,这成为数组的一个定义属性。不管你对一个长度为 N 的数组做什么(改变值、删除空值等),它总是一个长度为 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.
字符串的长度是偶然的;它不是字符串的属性,而是副产品。尽管 Java 字符串实际上是不可变的,但如果可以更改其内容,则可以更改其长度。去掉最后一个字符(如果可能)会降低长度。
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.
我知道这是一个很好的区别,我可能会被否决,但这是真的。如果我创建了一个长度为 4 的数组,那么这个长度为 4 的数组是该数组的一个定义特征,并且无论其中包含什么都是正确的。如果我创建一个包含“dogs”的字符串,则该字符串的长度为 4,因为它恰好包含四个字符。
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.
我认为这是用属性做一个而另一个用方法做的理由。事实上,这可能只是一种无意的不一致,但对我来说总是有意义的,这也是我一直以来的想法。
回答by Matthew
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.
我被告知对于数组,由于以下恐惧,不会通过方法检索长度:程序员只会在进入循环之前将长度分配给局部变量(想想 for 循环,其中条件使用数组的长度。)程序员应该这样做是为了减少函数调用(从而提高性能)。问题是在循环期间长度可能会改变,而变量不会。
回答by Gordon Gustafson
Consider:
考虑:
int[] myArray = new int[10];
String myString = "hello world!";
List<int> myList = new ArrayList<int>();
myArray.length // Gives the length of the array
myString.length() // Gives the length of the string
myList.size() // Gives the length of the list
It's very likely that strings and arrays were designed at different times and hence ended up using different conventions. One justification is that since Strings use arrays internally, a method, length()
, was used to avoid duplication of the same information. Another is that using a method length()
helps emphasize the immutability of strings, even though the size of an array is also unchangeable.
很可能字符串和数组是在不同的时间设计的,因此最终使用了不同的约定。一个理由是,由于字符串在内部使用数组length()
,因此使用了一种方法来避免重复相同的信息。另一个是使用方法length()
有助于强调字符串的不变性,即使数组的大小也是不可更改的。
Ultimately this is just an inconsistency that evolved that would definitely be fixed if the language were ever redesigned from the ground up. As far as I know no other languages (C#, Python, Scala, etc.) do the same thing, so this is likely just a slight flaw that ended up as part of the language.
最终,这只是一种进化的不一致,如果从头开始重新设计语言,肯定会得到解决。据我所知,没有其他语言(C#、Python、Scala 等)做同样的事情,所以这可能只是作为语言一部分的一个小缺陷。
You'll get an error if you use the wrong one anyway.
无论如何,如果您使用错误的方法,您将收到错误消息。
回答by Ryan
Whenever an array is created, its size is specified. So length can be considered as a construction attribute. For String, it essentially a char array. Length is a property of the char array. There is no need to put length as a field, because not everything needs this field. http://www.programcreek.com/2013/11/start-from-length-length-in-java/
每当创建数组时,都会指定其大小。所以长度可以被认为是一个构造属性。对于 String,它本质上是一个字符数组。长度是字符数组的一个属性。没有必要把长度作为一个字段,因为不是所有的东西都需要这个字段。 http://www.programcreek.com/2013/11/start-from-length-length-in-java/
回答by Saif
Let me first highlight three different ways for similar purpose.
让我首先强调出于类似目的的三种不同方式。
length
-- arrays(int[]
, double[]
, String[]
) -- to know the length of the arrays
length
-- arrays( int[]
, double[]
, String[]
) -- 知道数组的长度
length()
-- String related Object(String
, StringBuilder
, etc) -- to know the length of the String
length()
--字符串相关对象( String
, StringBuilder
, etc) -- 知道字符串的长度
size()
-- Collection Object(ArrayList
, Set
, etc) -- to know the size of the Collection
size()
-- Collection Object( ArrayList
, Set
, etc) -- 知道集合的大小
Now forget about length()
consider just length
and size()
.
现在忘记length()
只考虑length
和size()
。
length
is not a method, so it completely makes sense that it will not work on objects. It only works on arrays.size()
its name describes it better and as it is a method, it will be used in the case of those objects who work with collection (collection frameworks) as I said up there.
length
不是方法,因此它不适用于对象是完全有道理的。它只适用于数组。size()
它的名字更好地描述了它,并且因为它是一种方法,所以它将用于那些使用集合(集合框架)的对象的情况,正如我在上面所说的那样。
Now come to length()
:
String is not a primitive array (so we can't use .length
) and also not a Collection (so we cant use .size()
) that's why we also need a different one which is length()
(keep the differences and serve the purpose).
现在来length()
:
String 不是一个原始数组(所以我们不能使用.length
),也不是一个集合(所以我们不能使用.size()
),这就是为什么我们还需要一个不同的length()
(保留差异并达到目的)。
As answer to Why?
I find it useful, easy to remember and use and friendly.
作为答案为什么?
我发现它很有用,易于记忆和使用且友好。
回答by Prabandha
.length
is a one-off property of Java. It's used to find the size of a single dimensional array.
.length
是 Java 的一次性属性。它用于查找一维数组的大小。
.length()
is a method. It's used to find the length of a String
. It avoids duplicating the value.
.length()
是一种方法。它用于查找 a 的长度String
。它避免了重复值。
回答by Michael Dorner
I just want to add some remarks to the great answerby Fredrik.
The Java Language Specification in Section 4.3.1states
An objectis a class instanceor an array.
一个对象是一个类实例或一个数组。
So array has indeed a very special role in Java. I do wonder why.
所以数组在Java中确实有着非常特殊的作用。我不知道为什么。
One could argue that current implementation array is/was important for a better performance. But than it is an internal structure, which should not be exposed.
有人可能会争辩说,当前的实现数组对于更好的性能很重要。但它是一个内部结构,不应暴露。
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.
他们当然可以将属性屏蔽为方法调用并在编译器中处理它,但我认为在不是真正类的东西上使用方法会更加混乱。
I agree with Fredrik, that a smart compiler optimazation would have been the better choice. This would also solve the problem, that even if you use a property for arrays, you have not solved the problem for strings and other (immutable) collection types, because, e.g., string
is based on a char
array as you can see on the class definition of String
:
我同意 Fredrik 的观点,即智能编译器优化将是更好的选择。这也将解决这个问题,即使您使用数组的属性,您也没有解决字符串和其他(不可变)集合类型的问题,因为例如,正如您在类定义中看到的那样string
基于char
数组的String
:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[]; // ...
And I do not agree with that it would be even more confusing, because array does inherit all methods from java.lang.Object
.
而且我不同意这会更令人困惑,因为 array 确实从java.lang.Object
.
As an engineer I really do not like the answer "Because it has been always this way." and wished there would be a better answer. But in this case it seems to be.
作为一名工程师,我真的不喜欢“因为一直都是这样”的答案。并希望会有更好的答案。但在这种情况下,它似乎是。
tl;dr
tl;博士
In my opinion, it is a design flaw of Java and should not have implemented this way.
在我看来,这是 Java 的设计缺陷,不应该以这种方式实现。