数组的length属性在哪里定义?


263

我们可以ArrayList<E>使用它的public方法确定a的长度size(),例如

ArrayList<Integer> arr = new ArrayList(10);
int size = arr.size();

同样,我们可以确定 Array使用length属性对象

String[] str = new String[10];
int size =  str.length;

size()方法ArrayList是在ArrayList类内部定义的,而此的length属性在哪里Array定义在哪里?


在问题组织方面,我建议您提出一个问题:“在哪里定义Array的length属性?” 在进行所有说明之前,以防止您的帖子听起来像初学者的教程。
NoName

Answers:


250

数组是Java中的特殊对象,它们具有一个简单的属性,命名lengthfinal

没有数组的“类定义”(您无法在任何.class文件中找到它),它们是语言本身的一部分。

10.7。数组成员

数组类型的成员都是以下所有:

  • public final字段length,其中包含所述阵列的部件的数量。length可以是正数或零。
  • public方法clone,该方法将覆盖类中同名的方法Object,并没有抛出checked异常。clone数组类型方法的返回类型T[]T[]

    多维数组的克隆很浅,也就是说,它仅创建一个新数组。子数组是共享的。

  • 所有成员都继承了阶级Object; 唯一Object不被继承的clone方法是它的方法。

资源:


84
还要注意,它ArrayList.size()提供了实际存储在数组中的对象数,而myArray.length[])提供了“容量”。也就是说,如果for myArray = new int[10];,则返回10。这不是您放入数组中的对象的数量。
wmorrison365'2

1
@Colin数组对象有多么特别?我的意思是为什么设计人员需要使其变得特别,为什么不提供数组的类文件?
Vikas Verma 2014年

5
@VikasVerma为什么数组不像对象?因为历史。在设计Java时,在语法和样式上与C不同时,大多数语言创新尝试都失败了。因此,在那个时代,C ++,Objective-C和Java是少数几种避免晦涩的语言。Java被有意识地设计为包括花括号,基元和纯数组,以使当今的主流程序员熟悉。查看对James Gosling和其他Sun人员的采访。有些人坚持使用Collections进行纯OOP,并避免使用纯数组。
罗勒·布尔克

1
@VikasVerma,在某些时候,java必须基于较低级别的技术构建。如果java不存在,则无法使用java进行构建。您必须使用C ++(或其他方式,但本例中为C ++)来为Java的其余部分构建一些原始编译,以使其具有自身存在的上下文。在最终用C ++编写代码之前,您不可能拥有所有内容的类。您究竟将如何在Java中建立阵列?如果您不能使用,List因为这会在其实现中使用数组。
亚历山大·伯德

如果您想按原样回答,那么stackoverflow.com/a/50506451/1059372
尤金(Eugene)

114

它基本上是“特殊的”,带有自己的字节码指令:arraylength。所以这个方法:

public static void main(String[] args) {
    int x = args.length;
}

像这样编译成字节码:

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   arraylength
   2:   istore_1
   3:   return

因此不会像普通字段一样对其进行访问。的确,如果您试图像正常字段一样获取它,则它将失败:

// Fails...
Field field = args.getClass().getField("length");
System.out.println(field.get(args));

因此,不幸的是,每个具有公共final字段的数组类型的JLS描述length都有些误导:(


1
我不记得阿尔伯特·爱因斯坦的确切说法,但它的意思是“人们非常了解事物,只能以非常简单的方式解释事物”,我认为它非常适合您:)
JAVA

@Jon Skeet数组对象如何特殊我的意思是为什么设计人员需要使其特殊化,为什么不提供数组的类文件?
Vikas Verma 2014年

2
@VikasVerma:考虑一下数组对象的大小。所有其他类型都有固定的大小-每个实例的大小都相同,而数组根据其长度而变化。那只是一个例子。如果您认为无需使用任何特殊方法就可以达到相同的结果,那么您认为数组类的字段会是什么样?int[]当泛型不适用于原始类型时,您将如何表示?(而且,泛型已经很长时间不存在了。)通过对所有集合使用链接列表,您可以在没有数组的情况下摆脱困境,但是这样做效率极高。
乔恩·斯基特

@JonSkeet但是StringBuffer类类型也有固定大小吗?是的,的确是我在考虑泛型,但在我问谢谢之前你指出了。
Vikas Verma 2014年

@VikasVerma:StringBuffer类本身可以,是的-因为它持有对a的引用char[](或至少已经做到;我不知道它是否仍然可以立即使用)。因此,尽管a StringBuilder负责更多内存,但其立即大小和布局是固定的。
乔恩·斯基特

18

它在Java语言规范中定义:

数组类型的成员都是以下所有:

  • public final字段length,其中包含所述阵列的部件的数量。length可以是正数或零。

由于数组类型的数量是无限的(每个类都有一个对应的数组类型,然后是多维数组),所以不能在类文件中实现它们;JVM必须动态地做到这一点。


15

即使这不是问题的直接答案,它还是.lengthvs .size()参数的补充。我正在研究与此问题相关的内容,因此当我遇到该问题时,我注意到此处提供的定义

公共最终字段长度,其中包含array的组件数

是“不完全”正确的。

字段长度包含放置组件的可用位置数量,而不是数组中存在的组件数量。因此,它代表分配给该阵列的总可用内存,而不是该内存的多少已被填充。

阵列内存分配

例:

static class StuffClass {
    int stuff;
    StuffClass(int stuff) {
        this.stuff = stuff;
    }
}

public static void main(String[] args) {

    int[] test = new int[5];
    test[0] = 2;
    test[1] = 33;
    System.out.println("Length of int[]:\t" + test.length);

    String[] test2 = new String[5];
    test2[0] = "2";
    test2[1] = "33";    
    System.out.println("Length of String[]:\t" + test2.length);

    StuffClass[] test3 = new StuffClass[5];
    test3[0] = new StuffClass(2);
    test3[1] = new StuffClass(33);
    System.out.println("Length of StuffClass[]:\t" + test3.length);         
}

输出:

Length of int[]:        5
Length of String[]:     5
Length of StuffClass[]: 5

但是,的.size()属性ArrayList确实给出了列表中元素的数量:

ArrayList<Integer> intsList = new ArrayList<Integer>();
System.out.println("List size:\t" + intsList.size());
intsList.add(2);
System.out.println("List size:\t" + intsList.size());
intsList.add(33);
System.out.println("List size:\t" + intsList.size());

输出:

List size:  0
List size:  1
List size:  2

1
这是正确的,因为所有元素都初始化为零。数组不能是“空”
圭多

嗯,这正是我所说的。这不是“完全”正确的。即使没有添加任何数组,它的长度仍为5。因此,它并不“完全”包含数组中的元素数。您的评论只是我的回答的补充,不是使它不正确的理由。
nem035 2015年

如果您试图区分null和非null元素,则可能是“不正确的” 。但是区别不起作用。毕竟,size()(例如)a的List也可能包含null值。
史蒂芬·C

是的,本质上,我的观点是size行为动态,而length它是静态属性……数组中剩余的未填充空间被初始化为“ Non Values ”(取决于类型)这一事实与这一点并不矛盾。
nem035 '16

5

它是public final字段,其中包含数组的组件数(长度可以为正或零)

因此,数组与以下类具有相同的公共字段和方法:

class A implements Cloneable, java.io.Serializable {
    public final int length = X;
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

有关更多信息,请访问

10.7数组成员

http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html


0

要按原样回答,数组的length属性在哪里定义?在特别Object header

通过JOL轻松查看

 int [] ints = new int[23];
 System.out.println(ClassLayout.parseInstance(ints).toPrintable());

该输出的其中一行将是:

OFFSET  SIZE      TYPE DESCRIPTION
16       4        (object header)   17 00 00 00 (00010111 00000000 00000000 00000000) (23)

一般对象具有两个头(标记和克拉斯),阵列具有多一个总是占据4 bytes的长度,作为size是一个int


-1

关键字的长度就像定义的数据字段一样。在数组中使用时,我们可以使用它来访问数组中的元素数。关于String [],我们可以调用String类中定义的length()方法。关于ArrayList,我们可以使用ArrayList中定义的size()方法。请注意,使用ArrayList <>(capacity)创建一个数组列表时,该数组列表的初始size()为零,因为没有元素。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.