【问题标题】:Java: why Array.length has no () but String.length() does? [duplicate]Java:为什么 Array.length 没有 () 但 String.length() 有? [复制]
【发布时间】:2014-07-03 22:05:45
【问题描述】:

为什么当我们得到一个数组的长度时,我们不必放置 () 喜欢

int [] ar;
System.out.println(ar.length); // no parentheses 

但是对于一个字符串它会是

String st;
System.out.println(st.length());

【问题讨论】:

  • 我不同意这个问题与前面的问题相同,也不同意该问题的答案回答这个问题。前面的问题是“我如何找到这些不同实体的长度?”这个问题问“为什么我需要括号来获取字符串的长度而不是数组的长度?”我担心答案可能是“你只是这样做”,但无论如何它不会出现在另一个问题的答案中。
  • 我也不同意。这个问题是关于字段访问和方法之间的区别。如果详细介绍,这也是关于为什么在 Java-API 中有不同的实现。

标签: java


【解决方案1】:

为什么 Array.length 没有 () 而 String.length() 有?

在句法层面,这真的归结为“历史原因”和“因为这是 Java(pre)1.0 语言设计者决定这样做的”。唯一能真正告诉你为什么的人是语言设计者自己。

但是:

  • length 字段的特殊之处在于它实际上位于数组对象的标头中,并且获取数组的长度使用特殊的字节码。

  • length 字段不能以任何方式更改,除非有危险的本机代码黑客攻击。这样做非常重要,以避免堆损坏等问题。(相比之下,即使是普通对象上的 final 字段也可以使用反射进行修改。)

在这些方面,数组上的length 确实不同于任何其他字段。


自(前)Java 早期以来,在 API 中使用公开字段已经过时了。

大多数人会说这是一件好事。通过将长度信息公开为字符串、集合等的length()size() 方法,类库设计允许Java 实现者更改相应类型的表示。如果字段直接公开,这是不可能的(在 Java 中)。

【讨论】:

    【解决方案2】:

    区别在于:

    • 数组的length 与实际内容不是有关 - 它是维度!数组可以是length 10,但只能包含 2 个元素。
    • 一个包含元素的对象(字符串是一个对象,包含多个字符)内部可能有一定数量的对象。此计数可能会有所不同,具体取决于您是添加还是删除元素。所以length() 方法是关于实际内容的!

    原因是,数组是一种语言结构 - 因此,每当您想了解数组的某些信息(长度或其他)时,您都必须检索一个 固定 em> 来自 JVM 的值,而不是调用评估 something 的方法。

    Array-Class 只是实际 array-construct 的代理。)


    从技术上讲,array(注意小的a)只是内存中array.length 元素的内存分配。 (这就是为什么您不能简单地调整数组大小,而是在更改维度时总是需要创建一个新数组 - 它需要在内存中重新定位(在 C 中称为 realloc) ,所以有足够的空间容纳array.length * elementSize 位。

    另一方面,List 并不关心其元素在内存中的实际位置,因此允许随时动态调整大小。 (所以它可以服务一个方法size(),因为它有 no 维度,只需要返回关于它的内容的信息。)

    【讨论】:

    • 为了更好地表达你的观点,我查看了“语言合同”并找到了这个:stackoverflow.com/questions/10057524/… 但仍然无法建立联系。你能添加 1-2 行关于你在这里使用的语言结构吗
    【解决方案3】:

    这是访问字段(无括号)和调用方法(需要括号,即使该方法没有参数)之间的区别。

    从历史上看,数组可能有一个方法来补充或代替字段。除了方法之外,字符串可能还有一个字段。字段更简单,这可能是数组使用它的原因,但至少有两个原因可以让 String 有一个 length 方法:

    1. String 实现了CharSequence 接口,它定义了一个length() 方法,所以String 必须有那个方法。 (定义字段不是接口的特性,静态最终常量除外。)字符串可以有长度作为方法一个字段,但这会分散注意力。

    2. 灵活性。 String 的内部实现随着时间的推移发生了变化:曾经它使用一个内部 char 数组和单独的 offsetlength 字段,这些字段在 char 数组中定义了一个区域。这样做是为了让子字符串可以共享父字符串的 char 数组(具有不同的偏移量和长度),而不是复制数组。后来发现这种优化很少有好处,所以现在String只有一个大小正确的char数组,length方法读取数组的length字段。 String 不再有自己的长度字段,甚至没有私有字段,但如果它是类的公共 API 的一部分,他们就不能删除它,这会降低试验内部实现的灵活性。

      李>

    【讨论】:

    • CharSequence 是在 Java 1.4 中添加的,所以不是 Stringlength() 方法的原因。
    【解决方案4】:

    Array 的length 是一个int 字段,但String(和其他对象)通常使用getter 方法。

    请注意,两者的区别在于字符串的“长度”只是它已经存储在其内部char 数组中的信息量,而数组的length 字段只是它的容量。

    【讨论】:

    • 这就是为什么?为什么对象没有公共字段,为什么数组不是简单的长度方法?
    • @dognose 长度是一个可以访问的简单 final 字段。由于数组的长度是不可变的,因为您不能动态更改它的大小,因此可以公开该类的这一方面。
    • 字符串是不可变的,所以容量和长度总是一样的。
    • @MarkRotteveel 在反思的眼中,不在一个层次。当然,您不能将null 设置为char 数组,但是如果您使用像java.misc.Unsafe 这样的疯狂的东西,谁知道字符串,尤其是在参考长度方法时。数组的长度是不可设置的,即使是那种形式。
    猜你喜欢
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 2016-11-24
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多