【问题标题】:Where is array's length property defined?数组的长度属性在哪里定义?
【发布时间】:2012-03-07 01:28:13
【问题描述】:

我们可以使用ArrayList<E>的公共方法size()来确定ArrayList<E>的长度,比如

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

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

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

ArrayListsize() 方法是在ArrayList 类中定义的,那么Arraylength 属性在哪里定义?

【问题讨论】:

  • 在问题组织方面,我建议您提出问题“数组的长度属性在哪里定义?”在所有解释之前,以防止您的帖子听起来像初学者教程。

标签: java arrays


【解决方案1】:

数组是java中的特殊对象,它们有一个简单的属性,名为length,即final

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

10.7。数组成员

数组类型的成员都有以下几种:

  • publicfinal 字段length,其中包含数组的组件数。 length 可能是正数或零。
  • public 方法clone,它覆盖了类Object 中的同名方法并且不抛出任何检查异常。数组类型T[]clone方法的返回类型是T[]

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

  • 继承自类Object的所有成员; Object 唯一未被继承的方法是它的clone 方法。

资源:

【讨论】:

  • 还要注意ArrayList.size() 提供实际存储在数组中的对象数量,而myArray.length ([]) 提供“容量”。也就是说,如果对于myArray = new int[10];,它返回10。这不是您放入数组中的对象数。
  • @Colin 数组对象怎么这么特别我的意思是为什么设计师需要让它特别,为什么不提供数组的类文件?
  • @VikasVerma 为什么数组不像对象?因为历史。在设计 Java 时,大多数语言创新尝试在语法和风格上与 C 不同时都失败了。因此,C++、Objective-C 和 Java 是那个时代为数不多的摆脱默默无闻的语言。 Java 被有意设计为包含花括号 primitives 和普通数组,以使当时的主流程序员看起来很熟悉。请参阅对 James Gosling 和其他 Sun 人员的采访。有些人坚持使用纯 OOP 的集合,并避免使用普通数组。
  • @VikasVerma,在某些时候,java 必须建立在较低级别的技术上。如果 java 不存在,则无法使用 java 构建它。您必须使用 C++(或其他东西,但在这种情况下是 C++)为 java 的其余部分构建一些原始编译,以使其具有自身存在的上下文。如果没有最终触及用 C++ 编写代码的最低点,就不可能为所有内容创建类。你将如何在java中构建一个数组?如果您不能使用List,因为它在其实现中使用了数组。
  • 如果你想按原样回答,那么stackoverflow.com/a/50506451/1059372
【解决方案2】:

它基本上是“特殊的”,有自己的字节码指令: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));

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

【讨论】:

  • 我不记得阿尔伯特爱因斯坦的一句话,但它说的是“人们非常了解一件事只能用非常简单的方式解释事情”我认为它非常适合你: )
  • @Jon Skeet 数组对象有什么特别之处 我的意思是为什么设计师需要让它特别,为什么不提供数组的类文件?
  • @VikasVerma:想想数组对象的大小。所有其他类型都有固定的大小 - 每个实例的大小相同,而数组则根据它们的长度而变化。这只是一个例子。如果你认为你可以在不使用任何特殊的东西的情况下获得相同的结果,你认为数组类的字段会是什么样子?当泛型不适用于原始类型时,您将如何表示 int[]? (哎呀,无论如何,泛型在很长一段时间内都不存在。)您可以通过对所有集合使用链表来摆脱数组,但这会降低效率。
  • @JonSkeet 但是 StringBuffer 类类型也有固定大小呢?是的,我确实在考虑泛型,但你在我问谢谢之前指出了。
  • @VikasVerma:StringBuffer 类本身确实如此,是的 - 因为它包含对 char[] 的引用(或者至少确实如此;我不知道它是否仍然如此,关闭 -手)。因此,虽然StringBuilder 负责更多内存,但它的直接大小和布局是固定的。
【解决方案3】:

Java language specification中定义:

数组类型的成员都有以下几种:

  • public final 字段length,其中包含数组的组件数。 length 可以是正数或零。

由于数组类型的数量是无限的(每个类都有对应的数组类型,那么还有多维数组),它们不能在类文件中实现; JVM 必须即时执行。

【讨论】:

    【解决方案4】:

    尽管这不是问题的直接答案,但它是对 .length.size() 论点的补充。我正在研究与这个问题相关的东西,所以当我遇到它时,我注意到这里提供的定义

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

    不是“完全”正确的。

    字段长度包含放置组件的可用位置数,而不是数组中存在的组件数。所以它表示分配给该数组的总可用内存,而不是填充了多少内存。

    例子:

    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
    

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

    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
    

    【讨论】:

    • 这是正确的,因为所有元素都被初始化为零。数组不能为“空”
    • 这正是我所说的。这不是“完全”正确的。即使没有任何内容添加到数组中,它的长度仍然为 5。因此,它并不“完全”包含数组中元素的数量。您的评论只是对我的回答的补充,而不是使其不正确的理由。
    • 如果您试图区分 null 和非空元素,这可能是“不正确的”。但是区分不起作用。毕竟,(比如说)Listsize() 也可能包含null 值。
    • 是的,基本上我的意思是size 的行为是动态的,而length 是一个静态属性......事实上,数组中剩余的未填充空间被初始化为“Non值”(取决于类型)并不真正与这一点相矛盾。
    【解决方案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

    【讨论】:

      【解决方案6】:

      按原样回答,数组的这个长度属性在哪里定义?在一个特殊的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)
      

      通常,对象有两个标题(mark 和 klass),数组还有一个总是占用 4 bytes 的长度,因为 size 是一个 int

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 2022-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-23
          • 2021-02-13
          • 2011-05-21
          相关资源
          最近更新 更多