¿Dónde se define la propiedad de longitud de la matriz?

263

Podemos determinar la duración de un ArrayList<E>uso de su método público size(), como

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

Del mismo modo, podemos determinar la longitud de un Arrayobjeto utilizando la lengthpropiedad

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

Mientras que el size()método de ArrayListse define dentro de la ArrayListclase, ¿dónde está definida esta lengthpropiedad de Array?

BOBO
fuente
En cuanto a la organización de las preguntas, sugeriría plantear su pregunta "¿dónde se define la propiedad de longitud de la matriz?" antes de todas las explicaciones para evitar que tu publicación suene como un tutorial para principiantes.
NoName

Respuestas:

250

Las matrices son objetos especiales en Java, tienen un atributo simple llamado lengthcual es final.

No hay una "definición de clase" de una matriz (no se puede encontrar en ningún archivo .class), son parte del lenguaje en sí.

10.7 Miembros de la matriz

Los miembros de un tipo de matriz son todos los siguientes:

  • El public finalcampo length, que contiene el número de componentes de la matriz. lengthpuede ser positivo o cero
  • El publicmétodo clone, que anula el método del mismo nombre en clase Objecty no arroja excepciones marcadas. El tipo de retorno del clonemétodo de un tipo de matriz T[]es T[].

    Un clon de una matriz multidimensional es poco profundo, es decir, crea solo una nueva matriz. Las submatrices son compartidas.

  • Todos los miembros heredados de la clase Object; El único método Objectque no se hereda es su clonemétodo.

Recursos:

Colin Hebert
fuente
84
Tenga en cuenta también que ArrayList.size()proporciona el número de objetos realmente almacenados en la matriz, mientras que myArray.length( []) proporciona la "capacidad". Es decir, si es así, myArray = new int[10];devuelve 10. No es el número de objetos que ha puesto en la matriz.
wmorrison365
1
@Colin ¿Cómo los objetos de matriz son tan especiales? Quiero decir, ¿por qué los diseñadores deben hacerlo especial y por qué no proporcionar el archivo de clase de una matriz?
Vikas Verma
55
@VikasVerma ¿Por qué las matrices no son como objetos? Por la historia. Cuando se diseñó Java, la mayoría de los intentos de innovación del lenguaje fallaron cuando no eran similares a C en sintaxis y estilo. Por lo tanto, C ++, Objective-C y Java estuvieron entre los pocos lenguajes que escaparon a la oscuridad durante esa época. Java fue diseñado conscientemente para incluir llaves, primitivas y matrices simples para parecer familiares a los programadores convencionales de la época. Ver entrevistas con James Gosling y otras personas de Sun. Algunas personas se adhieren a las Colecciones para OOP puro y evitan las matrices simples.
Basil Bourque
1
@VikasVerma, en algún momento, Java debe estar basado en tecnología de nivel inferior. Si Java no existe, no puede construirlo con Java. Tienes que usar C ++ (o algo más, pero C ++ en este caso) para construir una compilación primitiva para que el resto de Java tenga contexto para su propia existencia. No puede tener clases para todo sin llegar a tocar fondo donde lo codifica en C ++. ¿Cómo exactamente construirías una matriz en Java? Si no puede usar un Listporque usa matrices en sus implementaciones.
Alexander Bird
si quieres responderlo tal cual , entonces stackoverflow.com/a/50506451/1059372
Eugene
114

Se trata de "especial", básicamente, con su propio código de bytes de instrucciones: arraylength. Entonces este método:

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

se compila en bytecode así:

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

Por lo tanto, no se accede como si fuera un campo normal. De hecho, si intenta obtenerlo como si fuera un campo normal, como este, falla:

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

Desafortunadamente, la descripción de JLS de cada tipo de matriz que tiene un campo final público lengthes algo engañosa :(

Jon Skeet
fuente
1
No recuerdo exactamente una cita de Albert Einstein, pero lo que dice es "la gente entiende muy bien una cosa solo puede explicar las cosas de una manera más simple", creo que te queda muy bien :)
JAVA
@ Jon Skeet ¿Cómo el objeto de matriz es especial? Quiero decir, ¿por qué los diseñadores deben hacerlo especial y por qué no proporcionar el archivo de clase de una matriz?
Vikas Verma
2
@VikasVerma: piense en el tamaño de un objeto de matriz. Todos los demás tipos tienen un tamaño fijo: cada instancia es del mismo tamaño, mientras que las matrices varían según su longitud. Ese es solo un ejemplo. Si cree que podría lograr los mismos resultados sin usar nada especial, ¿cómo cree que se verían los campos de una clase de matriz? ¿Cómo representaría int[]cuando los genéricos no se aplican a los tipos primitivos? (Y diablos, los genéricos no existían desde hace mucho tiempo de todos modos.) Usted podría escapar sin matrices, usando listas enlazadas para todas las colecciones, pero sería terrible para la eficiencia.
Jon Skeet
@ JonSkeet Pero, ¿qué pasa con el tipo de clase StringBuffer, también tiene un tamaño fijo? Sí, de hecho, estaba pensando en los genéricos, pero usted señala antes de pedirle gracias.
Vikas Verma
@VikasVerma: La StringBufferclase en sí, sí, porque contiene una referencia a un char[](o al menos lo hizo; no sé si todavía lo hace, de forma manual). Entonces, aunque a StringBuilderes responsable de más memoria, su tamaño y diseño inmediatos son fijos.
Jon Skeet
18

Está definido en la especificación del lenguaje Java :

Los miembros de un tipo de matriz son todos los siguientes:

  • El public finalcampo length, que contiene el número de componentes de la matriz. lengthpuede ser positivo o cero

Dado que hay un número ilimitado de tipos de matriz (para cada clase hay un tipo de matriz correspondiente, y luego hay matrices multidimensionales), no se pueden implementar en un archivo de clase; JVM tiene que hacerlo sobre la marcha.

Michael Borgwardt
fuente
15

Aunque esta no es una respuesta directa a la pregunta, es una adición al argumento .lengthvs. .size()Estaba investigando algo relacionado con esta pregunta, así que cuando la encontré me di cuenta de que las definiciones proporcionadas aquí

La longitud del campo público final, que contiene el número de componentes de la matriz .

no es "exactamente" correcto.

La longitud del campo contiene el número de lugares disponibles para colocar un componente, no el número de componentes presentes en la matriz. Por lo tanto, representa la memoria total disponible asignada a esa matriz, no la cantidad de memoria que se llena.

Asignación de memoria de matriz

Ejemplo:

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

Salida:

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

Sin embargo, la .size()propiedad del ArrayListda el número de elementos en la lista:

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

Salida:

List size:  0
List size:  1
List size:  2
nem035
fuente
1
Es correcto, ya que todos los elementos se inicializan a cero. Las matrices no pueden estar "vacías"
Guido
Bueno, eso es exactamente lo que dije. No es "exactamente" correcto. Todavía tiene una longitud de 5 a pesar de que no se agregó nada a la matriz. Por lo tanto, no contiene "exactamente" el número de elementos en la matriz. Su comentario es solo una adición a mi respuesta, no una razón para hacerlo incorrecto.
nem035
Podría ser "incorrecto" si intenta hacer una distinción entre nullelementos no nulos. Pero la distinción no funciona. Después de todo, el size()de (digamos) a Listpuede incluir nullvalores también.
Stephen C
Sí, esencialmente mi punto fue que se sizecomporta dinámicamente, mientras que lengthes una propiedad estática ... el hecho de que el espacio sin llenar restante en una matriz se inicializa a " No valores " (dependiendo del tipo) realmente no contradice este punto.
nem035
5

es el campo público final, que contiene el número de componentes de la matriz (la longitud puede ser positiva o cero)

Por lo tanto, una matriz tiene los mismos campos y métodos públicos que la siguiente clase:

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

más información en

10.7 Miembros de la matriz

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

Massimiliano Peluso
fuente
0

Para responder como está, ¿ dónde está definida esta propiedad de longitud de la matriz ? En un especial Object header.

Fácil de ver a través de JOL

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

Una de las líneas de esta salida será:

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

Por lo general, los objetos tienen dos encabezados (mark y klass), las matrices tienen uno más que siempre ocupan 4 byteslongitud, como sizees un int.

Eugene
fuente
-1

La longitud de la palabra clave actúa como un archivo de datos definido. Cuando se usa en una matriz, podemos usarla para acceder a cuántos elementos hay en una matriz. Con respecto a String [], podemos invocar el método length () definido en la clase String. Con respecto a ArrayList, podemos usar el método size () definido en ArrayList. Tenga en cuenta que al crear una lista de matriz con ArrayList <> (capacidad), el tamaño inicial () de esta lista de matriz es cero ya que no hay ningún elemento.

Xiaogang
fuente