Wo ist die Längeneigenschaft des Arrays definiert?

263

Wir können die Länge eines ArrayList<E>mit seiner öffentlichen Methode bestimmen size(), wie z

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

Ebenso können wir die Länge eines ArrayObjekts mithilfe der lengthEigenschaft bestimmen

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

Während die size()Methode von ArrayListinnerhalb der ArrayListKlasse definiert ist , wo ist diese lengthEigenschaft von Arraydefiniert?

NINCOMPOOP
quelle
In Bezug auf die Organisation der Fragen würde ich vorschlagen, Ihre Frage zu stellen: "Wo ist die Längeneigenschaft des Arrays definiert?" vor allen Erklärungen, um zu verhindern, dass Ihr Beitrag wie ein Tutorial für Anfänger klingt.
NoName

Antworten:

250

Arrays sind spezielle Objekte in Java, haben sie ein einfaches Attribut mit dem Namen , lengthdas ist final.

Es gibt keine "Klassendefinition" eines Arrays (Sie können sie in keiner .class-Datei finden), sie sind Teil der Sprache selbst.

10.7. Array-Mitglieder

Die Mitglieder eines Array-Typs sind alle die folgenden:

  • Das public finalFeld length, das die Anzahl der Komponenten des Arrays enthält. lengthkann positiv oder null sein.
  • Die publicMethode clone, die die gleichnamige Methode in der Klasse überschreibt Objectund keine geprüften Ausnahmen auslöst. Der Rückgabetyp der cloneMethode eines Array-Typs T[]ist T[].

    Ein Klon eines mehrdimensionalen Arrays ist flach, dh es wird nur ein einziges neues Array erstellt. Subarrays werden gemeinsam genutzt.

  • Alle von der Klasse geerbten Mitglieder Object; Die einzige Methode Object, die nicht vererbt wird, ist ihre cloneMethode.

Ressourcen:

Colin Hebert
quelle
84
Beachten Sie auch, dass dies ArrayList.size()die Anzahl der tatsächlich im Array gespeicherten Objekte angibt, während myArray.length( []) die "Kapazität" angibt. Das heißt, wenn für myArray = new int[10];, wird 10 zurückgegeben. Dies ist nicht die Anzahl der Objekte, die Sie in das Array eingefügt haben.
wmorrison365
1
@Colin Wie Array-Objekte so besonders sind Ich meine, warum müssen Designer sie speziell machen und warum nicht die Klassendatei eines Arrays bereitstellen?
Vikas Verma
5
@VikasVerma Warum sind Arrays keine Objekte? Wegen der Geschichte. Bei der Entwicklung von Java scheiterten die meisten Versuche zur Sprachinnovation, wenn sie in Syntax und Stil C nicht ähnlich waren. So gehörten C ++, Objective-C und Java zu den wenigen Sprachen, die sich in dieser Zeit der Dunkelheit entzogen haben. Java wurde bewusst so konzipiert, dass es geschweifte Klammern, Grundelemente und einfache Arrays enthält, die den Mainstream-Programmierern der damaligen Zeit vertraut erscheinen. Siehe Interviews mit James Gosling und anderen Sun-Leuten. Einige Leute halten sich an Sammlungen für reines OOP und vermeiden einfache Arrays.
Basil Bourque
1
@VikasVerma, irgendwann muss Java auf niedrigerer Technologie basieren. Wenn Java nicht existiert, können Sie es nicht mit Java erstellen. Sie müssen C ++ (oder etwas anderes, in diesem Fall aber C ++) verwenden, um eine primitive Kompilierung für den Rest von Java zu erstellen, damit der Kontext für seine eigene Existenz vorhanden ist. Sie können nicht für alles Klassen haben, ohne irgendwann den Tiefpunkt zu erreichen, an dem Sie ihn in C ++ codieren. Wie genau würden Sie ein Array in Java erstellen? Wenn Sie a nicht verwenden können, Listweil dies Arrays in ihren Implementierungen verwendet.
Alexander Bird
Wenn Sie es so beantworten möchten, wie es ist , dann stackoverflow.com/a/50506451/1059372
Eugene
114

Es ist im Grunde "speziell", mit einer eigenen Bytecode-Anweisung : arraylength. Also diese Methode:

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

wird wie folgt in Bytecode kompiliert:

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

Es wird also nicht so zugegriffen, als wäre es ein normales Feld. In der Tat, wenn Sie versuchen, es so zu bekommen, als wäre es ein normales Feld wie dieses, schlägt es fehl:

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

Leider ist die JLS-Beschreibung jedes Array-Typs mit einem öffentlichen lengthEndfeld etwas irreführend :(

Jon Skeet
quelle
1
Ich erinnere mich nicht genau an ein Zitat von Albert Einstein, aber es heißt: "Die Leute verstehen eine Sache sehr gut und können die Dinge nur auf sehr einfachere Weise erklären." Ich denke, es passt sehr gut zu dir :)
JAVA
@ Jon Skeet Wie speziell ein Array-Objekt ist Ich meine, warum müssen Designer es speziell machen und warum nicht eine Klassendatei eines Arrays bereitstellen?
Vikas Verma
2
@VikasVerma: Denken Sie an die Größe eines Array-Objekts. Alle anderen Typen haben eine feste Größe - jede Instanz hat dieselbe Größe, während Arrays je nach Länge variieren. Das ist nur ein Beispiel. Wenn Sie glauben, dass Sie dieselben Ergebnisse erzielen könnten, ohne etwas Besonderes zu verwenden, wie würden die Felder einer Array-Klasse Ihrer Meinung nach aussehen? Wie würden Sie darstellen, int[]wenn Generika nicht für primitive Typen gelten? (Und zum Teufel, Generika gab es sowieso lange nicht.) Sie könnten ohne Arrays davonkommen, indem Sie verknüpfte Listen für alle Sammlungen verwenden, aber es wäre für die Effizienz schrecklich.
Jon Skeet
@ JonSkeet Aber was ist mit dem StringBuffer-Klassentyp, der auch eine feste Größe hat? Ja, in der Tat habe ich über Generika nachgedacht, aber Sie weisen darauf hin, bevor ich Danke dafür fragte.
Vikas Verma
@VikasVerma: Die StringBufferKlasse selbst tut es, ja - weil sie einen Verweis auf a enthält char[](oder zumindest tat; ich weiß nicht, ob dies immer noch der Fall ist). Während a StringBuilderfür mehr Speicher verantwortlich ist, sind seine unmittelbare Größe und sein Layout festgelegt.
Jon Skeet
18

Es ist in der Java-Sprachspezifikation definiert :

Die Mitglieder eines Array-Typs sind alle die folgenden:

  • Das public finalFeld length, das die Anzahl der Komponenten des Arrays enthält. lengthkann positiv oder null sein.

Da es eine unbegrenzte Anzahl von Array-Typen gibt (für jede Klasse gibt es einen entsprechenden Array-Typ und dann mehrdimensionale Arrays), können sie nicht in einer Klassendatei implementiert werden. Die JVM muss dies im laufenden Betrieb tun.

Michael Borgwardt
quelle
15

Obwohl dies keine direkte Antwort auf die Frage ist, ist es eine Ergänzung zum Argument .lengthvs. .size()Ich habe etwas im Zusammenhang mit dieser Frage recherchiert und als ich darauf stieß, bemerkte ich, dass die Definition (en) hier bereitgestellt wurden

Die öffentliche endgültige Feldlänge, die die Anzahl der Komponenten des Arrays enthält .

ist nicht "genau" richtig.

Die Feldlänge enthält die Anzahl der verfügbaren Stellen zum Einfügen einer Komponente, nicht die Anzahl der im Array vorhandenen Komponenten. Es stellt also den gesamten verfügbaren Speicher dar, der diesem Array zugewiesen ist, und nicht, wie viel von diesem Speicher gefüllt ist.

Array-Speicherzuordnung

Beispiel:

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

Ausgabe:

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

Die .size()Eigenschaft von ArrayListgibt jedoch die Anzahl der Elemente in der Liste an:

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

Ausgabe:

List size:  0
List size:  1
List size:  2
nem035
quelle
1
Es ist richtig, da alle Elemente auf Null initialisiert werden. Arrays können nicht "leer" sein
Guido
Genau das habe ich gesagt. Es ist nicht "genau" richtig. Es hat immer noch eine Länge von 5, obwohl dem Array nichts hinzugefügt wurde. Daher enthält es nicht "genau" die Anzahl der Elemente im Array. Ihr Kommentar ist nur eine Ergänzung zu meiner Antwort, kein Grund, ihn falsch zu machen.
nem035
Es könnte "falsch" sein, wenn Sie versuchen, zwischen nullNicht-Null-Elementen zu unterscheiden. Aber die Unterscheidung funktioniert nicht. Schließlich kann das size()von (sagen wir) a Listauch nullWerte enthalten.
Stephen C
Ja, im Wesentlichen war mein Punkt, dass sizesich das Verhalten dynamisch verhält, während lengthes sich um eine statische Eigenschaft handelt. Die Tatsache, dass der verbleibende nicht ausgefüllte Speicherplatz in einem Array auf " Nicht-Werte " (abhängig vom Typ) initialisiert wird, widerspricht diesem Punkt nicht wirklich.
nem035
5

Es ist ein öffentliches Endfeld, das die Anzahl der Komponenten des Arrays enthält (Länge kann positiv oder Null sein).

Ein Array hat daher dieselben öffentlichen Felder und Methoden wie die folgende Klasse:

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

Weitere Infos unter

10.7 Array-Mitglieder

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

Massimiliano Peluso
quelle
0

Wo ist diese Längeneigenschaft des Arrays definiert, um es so zu beantworten, wie es ist ? In einem besonderenObject header .

Einfach über JOL zu sehen

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

Eine der Zeilen aus dieser Ausgabe lautet:

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

Normalerweise haben Objekte zwei Überschriften (mark und klass), Arrays haben eine weitere, die immer eine 4 bytesLänge einnimmt, ebenso sizewie eine int.

Eugene
quelle
-1

Die Schlüsselwortlänge verhält sich wie ein definiertes Datenfeld. Bei Verwendung in einem Array können wir damit auf die Anzahl der Elemente in einem Array zugreifen. In Bezug auf String [] können wir die in der String-Klasse definierte Methode length () aufrufen. In Bezug auf ArrayList können wir die in ArrayList definierte size () -Methode verwenden. Beachten Sie, dass beim Erstellen einer Array-Liste mit ArrayList <> (Kapazität) die Anfangsgröße () dieser Array-Liste Null ist, da kein Element vorhanden ist.

Xiaogang
quelle