Où la propriété length du tableau est-elle définie?

263

Nous pouvons déterminer la longueur d'un en ArrayList<E>utilisant sa méthode publique size(), comme

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

De même, nous pouvons déterminer la longueur d'un Arrayobjet en utilisant la lengthpropriété

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

Alors que la size()méthode de ArrayListest définie dans la ArrayListclasse, où est cette lengthpropriété de Arraydefined?

CORNICHON
la source
En termes d'organisation des questions, je suggère de poser votre question "où est définie la propriété de longueur de Array?" avant toutes les explications pour éviter que votre message ne ressemble à un tutoriel pour débutant.
NoName

Réponses:

250

Les tableaux sont des objets spéciaux en java, ils ont un attribut simple nommé lengthqui est final.

Il n'y a pas de "définition de classe" d'un tableau (vous ne pouvez le trouver dans aucun fichier .class), ils font partie du langage lui-même.

10.7. Membres du groupe

Les membres d'un type de tableau sont tous les suivants:

  • Le public finalchamp length, qui contient le nombre de composants du tableau. lengthpeut être positif ou nul.
  • La publicméthode clone, qui remplace la méthode du même nom dans la classe Objectet ne renvoie aucune exception vérifiée. Le type de retour de la cloneméthode d'un type tableau T[]est T[].

    Un clone d'un tableau multidimensionnel est peu profond, c'est-à-dire qu'il ne crée qu'un seul nouveau tableau. Les sous-réseaux sont partagés.

  • Tous les membres ont hérité de la classe Object; la seule méthode Objectqui n'est pas héritée est sa cloneméthode.

Ressources:

Colin Hebert
la source
84
Notez également que ArrayList.size()fournit le nombre d'objets réellement stockés dans le tableau tandis que myArray.length( []) fournit la "capacité". Autrement dit, si pour myArray = new int[10];, il renvoie 10. Ce n'est pas le nombre d'objets que vous avez mis dans le tableau.
wmorrison365
1
@Colin Comment les objets du tableau sont si spéciaux, je veux dire pourquoi les concepteurs doivent-ils le rendre spécial et pourquoi ne pas fournir le fichier de classe d'un tableau?
Vikas Verma
5
@VikasVerma Pourquoi les tableaux ne sont-ils pas comme des objets? À cause de l'histoire. Lorsque Java a été conçu, la plupart des tentatives d'innovation de langage ont échoué alors qu'elles n'étaient pas similaires à C dans la syntaxe et le style. Ainsi, C ++, Objective-C et Java étaient parmi les rares langages à échapper à l'obscurité à cette époque. Java a été consciemment conçu pour inclure des accolades, des primitives et des tableaux simples pour sembler familier aux programmeurs traditionnels de l'époque. Voir des interviews de James Gosling et d'autres gens de Sun. Certaines personnes s'en tiennent aux collections pour la POO pure et évitent les tableaux simples.
Basil Bourque
1
@VikasVerma, à un moment donné, java doit être construit sur une technologie de niveau inférieur. Si java n'existe pas, vous ne pouvez pas le construire avec java. Vous devez utiliser C ++ (ou autre chose, mais C ++ dans ce cas) pour construire une compilation primitive pour que le reste de Java ait un contexte pour sa propre existence. Vous ne pouvez pas avoir de classes pour tout sans finalement toucher le fond où vous le codez en C ++. Comment construiriez-vous exactement un tableau en Java? Si vous ne pouvez pas utiliser un Listcar cela utilise des tableaux dans leurs implémentations.
Alexander Bird
si vous voulez y répondre tel quel , alors stackoverflow.com/a/50506451/1059372
Eugene
114

Il est « spécial » au fond, avec sa propre instruction de bytecode: arraylength. Donc, cette méthode:

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

est compilé en bytecode comme ceci:

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

Il n'est donc pas accessible comme s'il s'agissait d'un champ normal. En effet, si vous essayez de l'obtenir comme s'il s'agissait d'un champ normal, comme celui-ci, il échoue:

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

Donc, malheureusement, la description JLS de chaque type de tableau ayant un champ final public lengthest quelque peu trompeuse :(

Jon Skeet
la source
1
je ne me souviens pas exactement d'une citation d'Albert Einstein mais ce qu'elle dit est que "les gens comprennent très bien une chose ne peuvent expliquer les choses que de manière très simple" je pense que cela vous convient très bien :)
JAVA
@ Jon Skeet En quoi un objet tableau est spécial Je veux dire pourquoi les concepteurs doivent-ils le rendre spécial et pourquoi ne pas fournir le fichier de classe d'un tableau?
Vikas Verma
2
@VikasVerma: pensez à la taille d'un objet tableau. Tous les autres types ont une taille fixe - chaque instance a la même taille, tandis que les tableaux varient en fonction de leur longueur. Ce n'est qu'un exemple. Si vous pensez que vous pourriez obtenir les mêmes résultats sans utiliser quelque chose de spécial, à quoi pensez-vous que les champs d'une classe de tableau ressembleraient? Comment représenteriez-vous int[]que les génériques ne s'appliquent pas aux types primitifs? (Et diable, les génériques n'existaient pas depuis longtemps de toute façon.) Vous pourriez vous en tirer sans tableaux en utilisant des listes liées pour toutes les collections, mais ce serait terrible pour l'efficacité.
Jon Skeet
@JonSkeet Mais qu'en est-il du type de classe StringBuffer, il a également une taille fixe? Oui, en effet, je pensais aux génériques, mais vous le faites remarquer avant de demander merci pour cela.
Vikas Verma
@VikasVerma: La StringBufferclasse elle-même le fait, oui - car elle contient une référence à un char[](ou l'a fait, du moins; je ne sais pas si elle le fait toujours, de manière autonome). Ainsi, alors que a StringBuilderest responsable de plus de mémoire, sa taille et sa disposition immédiates sont fixes.
Jon Skeet
18

Il est défini dans la spécification du langage Java :

Les membres d'un type de tableau sont tous les suivants:

  • Le public finalchamp length, qui contient le nombre de composants du tableau. lengthpeut être positif ou nul.

Puisqu'il y a un nombre illimité de types de tableaux (pour chaque classe il y a un type de tableau correspondant, et puis il y a des tableaux multidimensionnels), ils ne peuvent pas être implémentés dans un fichier de classe; la JVM doit le faire à la volée.

Michael Borgwardt
la source
15

Même si ce n'est pas une réponse directe à la question, c'est un ajout à l' argument .lengthvs. .size()Je cherchais quelque chose en rapport avec cette question, donc quand je l'ai rencontrée, j'ai remarqué que la ou les définitions fournies ici

La longueur finale du champ public, qui contient le nombre de composants du tableau .

n'est pas "exactement" correct.

La longueur du champ contient le nombre d' emplacements disponibles pour placer un composant, pas le nombre de composants présents dans le tableau. Il représente donc la mémoire totale disponible allouée à ce tableau, et non la quantité de cette mémoire qui est remplie.

Allocation de mémoire de baie

Exemple:

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

Production:

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

Cependant, la .size()propriété de la ArrayListdonne le nombre d'éléments dans la liste:

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

Production:

List size:  0
List size:  1
List size:  2
nem035
la source
1
C'est correct, car tous les éléments sont initialisés à zéro. Les tableaux ne peuvent pas être "vides"
Guido
Eh bien, c'est exactement ce que j'ai dit. Ce n'est pas "exactement" correct. Il a toujours une longueur de 5 même si rien n'a été ajouté au tableau. Ainsi, il ne contient pas "exactement" le nombre d'éléments du tableau. Votre commentaire n'est qu'un ajout à ma réponse, pas une raison de le rendre incorrect.
nem035
Cela peut être "incorrect" si vous essayez de faire une distinction entre les éléments nullet les éléments non nuls. Mais la distinction ne fonctionne pas. Après tout, le size()(disons) a Listpeut aussi inclure des nullvaleurs.
Stephen C
Yup, essentiellement mon point était que sizese comporte dynamiquement, tandis que lengthc'est une propriété statique ... le fait que l'espace restant non rempli dans un tableau est initialisé à " Non Values " (selon le type) ne contredit pas vraiment ce point.
nem035
5

c'est le champ final public, qui contient le nombre de composants du tableau (la longueur peut être positive ou nulle)

Un tableau a donc les mêmes champs et méthodes publics que la classe suivante:

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

plus d'infos sur

10.7 Membres de groupe

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

Massimiliano Peluso
la source
0

Pour y répondre tel quel, où est définie cette propriété de longueur du tableau ? Dans une spéciale Object header.

Facile à voir via JOL

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

L'une des lignes de cette sortie va être:

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

Habituellement, les objets ont deux en-têtes (mark et klass), les tableaux en ont un de plus qui occupent toujours 4 bytesen longueur, tout comme sizeun int.

Eugène
la source
-1

La longueur du mot clé agit comme une donnée déposée définie. Lors de l'utilisation dans un tableau, nous pouvons l'utiliser pour accéder au nombre d'éléments dans un tableau. Concernant String [], nous pouvons invoquer la méthode length () définie dans la classe String. En ce qui concerne ArrayList, nous pouvons utiliser la méthode size () définie dans ArrayList. Notez que lors de la création d'une liste de tableaux avec ArrayList <> (capacité), la taille initiale () de cette liste de tableaux est nulle car il n'y a pas d'élément.

Xiaogang
la source