Де визначається властивість довжини масиву?


263

Ми можемо визначити довжину , ArrayList<E>використовуючи його публічний метод size(), як

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

Аналогічно ми можемо визначити довжину Arrayоб’єкта за допомогою lengthвластивості

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

Тоді як size()метод ArrayListвизначено всередині ArrayListкласу, де ця lengthвластивість Arrayвизначена?


Щодо організації питань, я б запропонував поставити ваше питання "де визначено властивість довжини масиву?" перш ніж усі пояснення, щоб ваш пост не звучав як підручник для початківців.
NoName

Відповіді:


250

Масиви - це спеціальні об’єкти в java, вони мають простий атрибут, lengthякий називається final.

Немає "визначення класу" масиву (його не можна знайти в жодному файлі .class), вони є частиною самої мови.

10.7. Члени масиву

Членами типу масиву є всі наступні:

  • public finalПоле length, яке містить число компонентів масиву. lengthможе бути додатним або нульовим.
  • Чи не publicметод clone, який перекриває метод того ж імені в класі Objectі кидки не перевіряє виключення. Тип повернення cloneметоду типу масиву T[]є T[].

    Клон багатовимірного масиву неглибокий, що означає, що він створює лише один новий масив. Підмагістралі спільні.

  • Усі члени, успадковані від класу Object; єдиний метод, Objectякий не успадковується, - це його cloneметод.

Ресурси:


84
Зауважимо також, що ArrayList.size()надається кількість об'єктів, фактично збережених у масиві, тоді як myArray.length( []) забезпечує "ємність". Тобто, якщо для myArray = new int[10];, він повертає 10. Це не кількість об'єктів, які ви помістили в масив.
wmorrison365

1
@Colin Наскільки об’єкти масиву настільки особливі, я маю на увазі, чому дизайнерам потрібно зробити його спеціальним і чому не надавати файл класу масиву?
Вікас Верма

5
@VikasVerma Чому масиви не схожі на об'єкти? Через історію. Коли розроблялася Java, більшість спроб мовної інновації зазнали невдач, якщо вони не схожі на C у синтаксисі та стилі. Таким чином, C ++, Objective-C і Java були одними з небагатьох мов, які могли уникнути невідомості в той час. Java була свідомо розроблена таким чином, щоб включати фігурні дужки, примітиви та прості масиви, які здаються знайомими основним програмістам дня. Перегляньте інтерв'ю з Джеймсом Гослінгом та іншими людьми, що перебувають у Сонці. Деякі люди дотримуються колекції для чистого OOP і уникають простих масивів.
Василь Борк

1
@VikasVerma, в якийсь момент Java повинна будуватися за технологією нижчого рівня. Якщо java не існує, ви не можете побудувати її з java. Ви повинні використовувати C ++ (або щось інше, але C ++ в цьому випадку), щоб побудувати якусь примітивну компіляцію для решти Java, щоб мати контекст для власного існування. Ви не можете мати заняття для всього, якщо в кінцевому підсумку не потрапите на дно скелі, де ви кодуєте це на C ++. Як саме ви створили б масив у Java? Якщо ви не можете використовувати a, Listтому що він використовує масиви у своїх реалізаціях.
Олександр Птах

якщо ви хочете відповісти так, як є , тоді stackoverflow.com/a/50506451/1059372
Євген

114

Це «спеціальний» в основному, зі своєю інструкцією байткода: 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 кожного типу масиву, що має остаточне публічне поле length, дещо вводить в оману :(


1
я не пам'ятаю точно цитату Альберта Ейнштейна, але те, що вона говорить - це "люди дуже добре розуміють річ, можуть пояснити речі лише дуже простішим способом", я думаю, що вона вам дуже підходить :)
JAVA

@Jon Skeet Наскільки особливий об’єкт масиву, я маю на увазі, чому дизайнерам потрібно зробити його спеціальним і чому не надавати файл класу масиву?
Вікас Верма

2
@VikasVerma: Подумайте про розмір об'єкта масиву. Усі інші типи мають фіксований розмір - кожен екземпляр однакового розміру, тоді як масиви змінюються залежно від їх довжини. Це лише один приклад. Якщо ви думаєте, що ви могли б досягти однакових результатів, не використовуючи нічого особливого, як ви думаєте, як виглядатимуть поля класу масиву? Як би ви представляли, int[]коли дженерики не застосовуються до примітивних типів? (І чорт, дженерики так і не існували довгий час.) Ви можете піти без масивів, використовуючи пов'язані списки для всіх колекцій, але це було б жахливо за ефективністю.
Джон Скіт

@JonSkeet Але що з типом класу StringBuffer він також має фіксований розмір? Так, я справді думав про дженерики, але ви зазначаєте, перш ніж я попросив подяку за це.
Вікас Верма

@VikasVerma: Сам StringBufferклас так, так - тому що він містить посилання на char[](або, принаймні, я не знаю, чи все ще є, поза рукою). Отже, хоча a StringBuilderвідповідає за більшу кількість пам'яті, її безпосередній розмір та макет виправлені.
Джон Скіт

18

Це визначено в специфікації мови Java :

Членами типу масиву є всі наступні:

  • public finalПоле length, яке містить число компонентів масиву. lengthможе бути додатним або нульовим.

Оскільки існує безмежна кількість типів масивів (для кожного класу є відповідний тип масиву, а потім є багатовимірні масиви), вони не можуть бути реалізовані у файлі класу; JVM має робити це на льоту.


15

Незважаючи на те, що це не пряма відповідь на питання, це доповнення до аргументу .lengthvs. .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

Однак, .size()властивість ArrayListцього елемента дає кількість елементів у списку:

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

1
Це правильно, оскільки всі елементи ініціалізовані до нуля. Масиви не можуть бути "порожніми"
Гідо

Ну це саме те, що я сказав. Це не "точно" правильно. Він досі має довжину 5, навіть якщо до масиву нічого не додано. Таким чином, він не "точно" містить кількість елементів у масиві. Ваш коментар - лише доповнення до моєї відповіді, а не привід зробити його неправильним.
nem035

Це може бути "неправильно", якщо ви спробуєте розмежувати nullелементи та ненулі елементи. Але відмінність не працює. Зрештою, в size()(скажімо, a) Listможе бути включено і nullзначення.
Стівен С

Так, по суті, я вважаю, що sizeдинамічно поводиться, а lengthстатична властивість ... той факт, що залишився незаповнений простір у масиві ініціалізується на " Незначні значення " (залежно від типу) насправді не суперечить цьому.
nem035

5

це публічне підсумкове поле, яке містить кількість компонентів масиву (довжина може бути додатною або нульовою)

Таким чином, масив має ті ж загальнодоступні поля та методи, що й наступний клас:

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


0

Щоб відповісти на нього як є, де визначена ця властивість довжини масиву ? У спеціальному 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)

Зазвичай об'єкти мають два заголовки (марка та клас), масиви мають ще один, який завжди займає 4 bytesдовжину, як sizeі an int.


-1

Довжина ключового слова діє подібно до поданих даних. Під час використання в масиві ми можемо використовувати його для доступу до кількості елементів масиву. Що стосується String [], ми можемо викликати метод length (), визначений у класі String. Що стосується ArrayList, ми можемо використовувати метод size (), визначений у ArrayList. Зауважте, що при створенні списку масивів зі ArrayList <> (місткість) початковий розмір () цього списку масивів дорівнює нулю, оскільки немає елемента.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.