Java中的长度和长度()

时间:2009-12-27 08:21:08

标签: java arrays string

为什么我们将数组的长度作为属性array.length,而对于String我们有一个方法str.length()

有什么原因吗?

8 个答案:

答案 0 :(得分:95)

首先,我要强调三种不同的方式,以达到类似目的。

length - 数组int[]double[]String[]) - 了解数组的长度

length() - 与字符串相关的对象StringStringBuilder等) - 知道字符串的长度

size() - 集合对象ArrayListSet等) - 了解集合的大小

现在忘记length()只考虑lengthsize()

length不是一种方法,因此完全有意义的是它不能用于对象。它只适用于阵列 size()它的名称描述得更好,因为它是一种方法,它将用于那些使用集合(集合框架)的对象,就像我在那里所说的那样。

现在来 length()
字符串不是原始数组(因此我们不能使用.length)而不是集合(因此我们无法使用.size())这就是为什么我们还需要另一个length() (保持差异并达到目的)。

作为答案为什么?
我发现它很有用,易于记忆,使用和友好。

答案 1 :(得分:25)

有点简化你可以把它想象成数组是特殊情况而不是普通类(有点像基元,但不是)。字符串和所有集合都是类,因此是获取大小,长度或类似事物的方法。

我猜设计时的原因是性能。如果他们今天创建它们,他们可能会想出类似数组支持的集合类。

如果有人有兴趣,这里有一小段代码来说明生成代码中两者之间的区别,首先是源代码:

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());
  }
}

切换字节代码中不那么重要的部分,在类上运行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

在第一种情况(20-25)中,代码只询问JVM数组的大小(在JNI中这可能是对GetArrayLength()的调用)而在String情况下(28-35)它需要做一个方法调用来获取长度。

在20世纪90年代中期,如果没有好的JIT和东西,它会完全杀死性能只有java.util.Vector(或类似的东西),而不是一个语言结构,它实际上并不像一个类,但是快速。他们当然可以将属性作为方法调用进行掩码并在编译器中处理它,但我认为在某些不是真正的类的方法上使用方法会更加困惑。

答案 2 :(得分:7)

考虑:

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

字符串和数组很可能是在不同的时间设计的,因此最终使用了不同的约定。一个理由是,由于字符串在内部使用数组,因此使用方法length()来避免重复相同的信息。另一个是使用方法length()有助于强调字符串的不变性,即使数组的大小也是不可更改的。

最终,这只是一种不一致的演变,如果语言从头开始重新设计,肯定会被修复。据我所知,没有其他语言(C#,Python,Scala等)做同样的事情,所以这可能只是一个轻微的缺陷,最终成为语言的一部分。

如果你使用了错误的话,你会收到错误。

答案 3 :(得分:7)

.length 是Java的一次性属性。它用于查找单维数组的大小。

.length() 是一种方法。它用于查找 String 的长度。它避免重复该值。

答案 4 :(得分:2)

在Java中,Array将其长度与实际保存数据的结构分开存储。创建数组时,指定其长度,这将成为数组的定义属性。无论你对长度为N的数组做什么(改变值,无效等等),它总是一个长度为N的数组。

字符串的长度是偶然的;它不是String的属性,而是副产品。虽然Java Strings实际上是不可变的,但是如果可以改变它们的内容,你可以改变它们的长度。敲掉最后一个字符(如果可能的话)会降低长度。

我知道这是一个很好的区别,我可能会因此而被投票,但这是真的。如果我创建一个长度为4的数组,则该长度为4的数组是数组的定义特征,无论其内部是什么,都是如此。如果我创建一个包含“dogs”的String,那个String的长度为4,因为它恰好包含四个字符。

我认为这是使用属性做一个而用方法做另一个的理由。事实上,它可能只是一种无意的不一致,但它总是对我有意义,而这总是我对它的看法。

答案 5 :(得分:1)

我被教导说,对于数组,由于以下的恐惧,不能通过方法检索长度:程序员只需在进入循环之前将长度分配给局部变量(想想条件使用数组长度的for循环。程序员应该这样做以减少函数调用(从而提高性能)。问题是循环期间长度可能会改变,而变量则不会。

答案 6 :(得分:0)

每当创建一个数组时,都会指定其大小。因此长度可以被视为构造属性。对于String,它本质上是一个char数组。 Length是char数组的属性。没有必要将长度作为一个字段,因为不是所有东西都需要这个字段。 http://www.programcreek.com/2013/11/start-from-length-length-in-java/

答案 7 :(得分:-1)

我只是想通过answer向好Fredrik添加一些评论。

Java Language Specification in Section 4.3.1

  

对象类实例数组

因此,数组在Java中确实扮演着非常特殊的角色。我不知道为什么。

有人可能会争辩说,当前的实现阵列对于提高性能非常重要。但它不是一个内部结构,不应该暴露。

  

他们当然可以将属性作为方法调用进行掩码并在编译器中处理它,但我认为在某些不是真正的类的方法上使用方法会更加令人困惑。

我同意Fredrik的观点,认为聪明的编译器优化会是更好的选择。这也可以解决这个问题,即使你对数组使用属性,也没有解决字符串和其他(不可变)集合类型的问题,因为,例如,string基于char您可以在String的类定义中看到数组:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {           
    private final char value[]; // ...

我不同意这会更令人困惑,因为数组确实继承了all methods from java.lang.Object

作为一名工程师,我真的不喜欢这个答案“因为它总是这样。”并希望有更好的答案。但在这种情况下似乎是。

<强> TL;博士

在我看来,这是Java的设计缺陷,不应该以这种方式实现。