Gdzie jest zdefiniowana właściwość długości tablicy?


263

Możemy określić długość ArrayList<E>korzystania z jego metody publicznej size(), np

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

Podobnie możemy określić długość Arrayobiektu za pomocą lengthwłaściwości

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

Podczas gdy size()metoda ArrayListjest zdefiniowana wewnątrz ArrayListklasy, gdzie ta lengthwłaściwość jest Arrayzdefiniowana?


Jeśli chodzi o organizację pytań, sugerowałbym postawienie pytania „gdzie jest zdefiniowana właściwość Array? przed wszystkimi objaśnieniami, aby Twój post nie brzmiał jak samouczek dla początkujących.
NoName

Odpowiedzi:


250

Tablice są specjalnymi obiektami w Javie, mają prosty atrybut o nazwie, lengthktóry jest final.

Nie ma „definicji klasy” tablicy (nie można jej znaleźć w żadnym pliku .class), są one częścią samego języka.

10,7 Członkowie tablicy

Członkami typu tablic są:

  • public finalPole length, które zawiera liczbę elementów macierzy. lengthmoże być dodatnia lub zerowa.
  • publicMetoda clone, która zastępuje metodę o tej samej nazwie w klasie Objecti nie rzuca sprawdzane wyjątki. Typem zwracanym clonemetody typu tablicowego T[]jest T[].

    Klon wielowymiarowej tablicy jest płytki, co oznacza, że ​​tworzy tylko jedną nową tablicę. Podziemne tablice są wspólne.

  • Wszyscy członkowie odziedziczyli po klasie Object; jedyną metodą, Objectktóra nie jest dziedziczona, jest jej clonemetoda.

Zasoby:


84
Zauważ też, że ArrayList.size()podaje liczbę obiektów faktycznie przechowywanych w tablicy, podczas gdy myArray.length( []) zapewnia „pojemność”. To znaczy, że jeśli myArray = new int[10];, zwraca 10. Nie jest to liczba obiektów, które umieściłeś w tablicy.
wmorrison365

1
@Colin Jak obiekty tablicy są tak wyjątkowe? Mam na myśli to, dlaczego projektanci muszą uczynić to wyjątkowym, a dlaczego nie dostarczyć pliku klasy tablicy?
Vikas Verma,

5
@VikasVerma Dlaczego tablice nie są jak obiekty? Z powodu historii. Podczas projektowania Java większość prób innowacji językowych nie powiodła się, jeśli nie jest podobna do C pod względem składni i stylu. Tak więc C ++, Objective-C i Java były jednymi z niewielu języków, które uniknęły niejasności w tej erze. Java została świadomie zaprojektowana w taki sposób, aby zawierała nawiasy klamrowe, prymitywne i proste tablice, aby wyglądały znajomo dla współczesnych programistów. Zobacz wywiady z Jamesem Goslingiem i innymi ludźmi z Sun. Niektórzy ludzie trzymają się Kolekcji dla czystego OOP i unikają prostych tablic.
Basil Bourque,

1
@VikasVerma, w pewnym momencie Java musi być zbudowana na technologii niższego poziomu. Jeśli java nie istnieje, nie można go zbudować za pomocą java. Musisz użyć C ++ (lub czegoś innego, ale C ++ w tym przypadku), aby zbudować prymitywną kompilację, aby reszta java miała kontekst dla własnego istnienia. Nie możesz mieć klas na wszystko bez ostatecznego uderzenia w dno, gdzie kodujesz w C ++. Jak dokładnie zbudowałbyś tablicę w Javie? Jeśli nie możesz użyć, Listponieważ używa to tablic w ich implementacjach.
Alexander Bird

jeśli chcesz odpowiedzieć tak, jak jest , to stackoverflow.com/a/50506451/1059372
Eugene

114

To „specjalne” w zasadzie, z własnej instrukcji kodu bajtowego: arraylength. Więc ta metoda:

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

jest skompilowany do kodu bajtowego w ten sposób:

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

Więc nie jest dostępny, jakby to było normalne pole. Rzeczywiście, jeśli spróbujesz uzyskać go tak, jakby to było normalne pole, takie jak to, nie powiedzie się:

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

Niestety, opis JLS każdego typu tablicy mającej publiczne pole końcowe lengthjest nieco mylący :(


1
nie pamiętam dokładnie cytatu Alberta Einsteina, ale mówi się, że „ludzie rozumieją coś bardzo dobrze, mogą tylko wyjaśnić to w bardzo prostszy sposób”, myślę, że bardzo ci to odpowiada :)
JAVA

@Jon Skeet Jak obiekt tablicy jest wyjątkowy Mam na myśli, dlaczego projektanci muszą go uczynić wyjątkowym i dlaczego nie dostarczyć pliku klasy tablicy?
Vikas Verma,

2
@VikasVerma: Pomyśl o wielkości obiektu tablicy. Wszystkie pozostałe typy mają stały rozmiar - każda instancja ma ten sam rozmiar, a tablice różnią się w zależności od ich długości. To tylko jeden przykład. Jeśli uważasz, że możesz osiągnąć te same wyniki bez użycia specjalnych elementów, jak myślisz, jak wyglądałyby pola klasy tablicowej? Jak byś reprezentował, int[]gdy leki ogólne nie mają zastosowania do typów pierwotnych? (I cholery, leki generyczne nie istniał przez długi czas w każdym razie.) Państwo mogli uciec bez tablic przy użyciu związane list do wszystkich kolekcji, ale to byłoby straszne dla wydajności.
Jon Skeet

@JonSkeet Ale co z typem klasy StringBuffer, który ma również stały rozmiar? Tak, rzeczywiście myślałem o rodzajach, ale zwróciłeś uwagę, zanim poprosiłem o podziękowanie.
Vikas Verma,

@VikasVerma: Sama StringBufferklasa ma, tak - ponieważ zawiera odniesienie do char[](lub przynajmniej zrobiła; nie wiem, czy nadal tak jest, z ręki). Więc chociaż a StringBuilderjest odpowiedzialne za więcej pamięci, jego bezpośredni rozmiar i układ są stałe.
Jon Skeet,

18

Jest zdefiniowany w specyfikacji języka Java :

Członkami typu tablic są:

  • public finalPole length, które zawiera liczbę elementów macierzy. lengthmoże być dodatnia lub zerowa.

Ponieważ istnieje nieograniczona liczba typów tablic (dla każdej klasy istnieje odpowiedni typ tablic, a następnie istnieją tablice wielowymiarowe), nie można ich zaimplementować w pliku klasy; JVM musi to robić w locie.


15

Chociaż nie jest to bezpośrednia odpowiedź na pytanie, jest dodatkiem do argumentu .lengthvs. .size()Badałem coś związanego z tym pytaniem, więc kiedy się z nim spotkałem, zauważyłem, że podano tu definicję (definicje)

Publiczna końcowa długość pola, która zawiera liczbę składników tablicy .

nie jest „dokładnie” poprawne.

Długość pola zawiera liczbę dostępnych miejsc do umieszczenia komponentu, a nie liczbę komponentów obecnych w tablicy. Oznacza to całkowitą dostępną pamięć przydzieloną do tej tablicy, a nie ilość tej pamięci.

Przydział pamięci macierzy

Przykład:

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

Wynik:

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

Jednak .size()właściwość ArrayListdaje liczbę elementów na liście:

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

Wynik:

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

1
Jest to poprawne, ponieważ wszystkie elementy są inicjowane na zero. Tablice nie mogą być „puste”
Guido

Właśnie to powiedziałem. To nie jest „dokładnie” poprawne. Nadal ma długość 5, mimo że nic nie zostało dodane do tablicy. Dlatego też nie „dokładnie” zawiera liczbę elementów w tablicy. Twój komentarz jest tylko dodatkiem do mojej odpowiedzi, a nie powodem, aby była niepoprawna.
nem035

Może to być „niepoprawne”, jeśli spróbujesz wprowadzić rozróżnienie między nullelementami niepustymi. Ale rozróżnienie nie działa. W końcu size()(powiedzmy) a Listmoże także zawierać nullwartości.
Stephen C

Tak, zasadniczo chodziło mi o to, że sizezachowuje się dynamicznie, podczas gdy lengthjest właściwością statyczną ... fakt, że pozostała niewypełniona przestrzeń w tablicy jest inicjowana na „ Non Values ” (w zależności od typu) tak naprawdę nie zaprzecza temu punktowi.
nem035

5

jest to publiczne pole końcowe, które zawiera liczbę elementów tablicy (długość może być dodatnia lub zero)

Tablica ma zatem te same publiczne pola i metody, co następująca klasa:

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

więcej informacji na

10.7 Członkowie tablicy

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


0

Aby odpowiedzieć tak, jak jest, gdzie jest zdefiniowana ta właściwość długości tablicy ? W specjalnym Object header.

Łatwo zobaczyć za pomocą JOL

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

Jednym z wierszy tego wyjścia będzie:

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

Zwykle obiekty mają dwa nagłówki (znak i klass), tablice mają jeszcze jeden, który zawsze zajmuje 4 bytesdługość, tak jak sizejest int.


-1

Długość słowa kluczowego działa jak zdefiniowane dane. Korzystając z tablicy, możemy jej użyć, aby uzyskać dostęp do liczby elementów w tablicy. W odniesieniu do String [] możemy wywołać metodę length () zdefiniowaną w klasie String. W odniesieniu do ArrayList możemy użyć metody size () zdefiniowanej w ArrayList. Zauważ, że podczas tworzenia listy tablic za pomocą ArrayList <> (pojemność), początkowy rozmiar () tej listy tablic wynosi zero, ponieważ nie ma elementu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.