Статьи

Pro Java

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

Масиви відносяться до посилальним типам даних, власне як і всі інші типи, крім примітивних. Нагадаю ще раз, що в Java все є об'єктом, виняток становлять лише примітивні типи.

Масиви можуть бути одновимірними і багатовимірними.

Процес створення масиву можна розділити на три етапи:

  • Оголошення (declaration)
  • Створення (instantation)
  • Ініціалізація (initialization)

Оголошення (declaration) масиву

На цьому етапі визначається тільки змінна типу посилання (reference) на масив, що містить тип масиву. Для цього записується ім'я типу елементів масиву, квадратними дужками вказується, що оголошується посилання на масив, а не проста змінна, і перераховуються імена змінних посилального типу, наприклад:

int

[] Numbers; // numbers посилання масив int-ів
String [] str; // str посилання на масив строк
byte [] [] twoBytes; // twoBytes посилання на двовимірний масив байтів
char [] letters, digits; // letters і digits посилання на масиви символів

По суті оголошення масивів, точно така ж операція як і оголошення будь-яких інших типів даних, правда має трохи свій синтаксис, так як це все таки масиви.

Java підтримує ще один синтаксис оголошення змінних типу масив, що забезпечує сумісність з С і С ++. Згідно з цим синтаксису одна чи кілька пар квадратних дужок слідують за ім'ям змінної, а не за ім'ям типу:

byte

arrayOfBytes

[]; // То ж, що і byte [] arrayOfBytes
byte arrayOfArrayOfBytes [] []; // То ж, що і byte [] [] arrayOfArrayOfBytes
byte [] arrayOfArrayOfBytes []; // То ж, що і byte [] [] arrayOfArrayOfBytes

Однак найчастіше такий синтаксис збиває з пантелику, тому його слід уникати. У наступному прикладі, легко сплутати що малося на увазі:

float

rates

[], maxRate; // може хотіли оголосити два масиви?

Такий синтаксис не рекомендується використовувати, так як вже говорилося, що він збиває з пантелику, крім того, в угоди з оформлення Java коду, рекомендується синтаксис, який був приведений першим, тобто квадратні дужки слідують відразу за типом оголошується масиву.

В даному випадку оголошені масив значень типу float з ім'ям rates і змінна типу float - maxRate.

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

Слід розуміти, що дана операція оголошення масиву ще не створює масив, а тільки оголошує змінну що є посиланням на нього, яку без ініціалізації не можна використовувати в програмі, так як компілятор видасть помилку, що змінна масиву не инициализирована.

Поки оголошена змінна масиву не визначена, вона може містити (якщо ви надасте) значення null. І тільки після визначення вона буде містити посилання на конкретний об'єкт.

Вказати довжину масиву при оголошенні змінної масиву неможливо, оскільки розмір є строго функцією об'єкта масиву, а не посилання на нього.

Важливо розуміти різницю між посиланням на масив (ім'я змінної масиву) і самим масивом, тобто об'єктом, на який вказує це посилання.

Створення (instantation) масиву

На цьому етапі вказується кількість елементів масиву, зване його розміром, виділяється місце для масиву в оперативній пам'яті, змінної-посилання присвоюється оператором = адреса масиву. Всі ці дії проводяться оператором new за яким слідує тип елементів масиву. наприклад:

letters

= New char [10]; // створили масив char-ів розмірів в 10 елементів

Але варто ще раз зауважити, що до цього змінна letters, повинна бути оголошена як масив. Щоб було зрозуміліше, це можна уявити ось так:

char

[] Letters; // оголосили letters як посилання на масив символів char
letters = new char [10]; // створили масив char-ів розмірів в 10 елементів

Під час створення масиву з таким синтаксисом всі елементи масиву автоматично не започатковано значеннями за замовчуванням. Це false для значень boolean, '\ u0000' для значень char, 0 для цілих значень, 0.0 для значень з плаваючою точкою і null для об'єктів або масивів.

В Java размер масиву фіксований. Створений масив не можна збільшити або зменшити. Бажаний розмір створюваного масиву задається невід'ємним цілим числом. Але в будь-який час змінної типу масиву може бути зіставлений новий масив іншого розміру. Тобто може бути присвоєна посилання на інший масив того ж типу що і оголошена змінна.

Індекси масивів завжди починаються з 0.

Перші дві операції: оголошення та створення масиву можна об'єднати в один оператор. наприклад:

char

[] Letters = new char [10];

Цей оператор еквівалентний двом наведеним вище.

Після даної операції змінна letters буде вже містити посилання на масив і якщо спробувати вивести її значення то ми отримаємо значення, що щось подібне до [C @ 659e0bfd. А все елементи масиву, як уже говорилося міститимуть значення за замовчуванням для оголошеного типу.

Створити масив можна тільки за допомогою оператора new, але посилання на вже існуючий масив можна привласнити іншим посиланням того ж типу. наприклад:

int

[] A = new int [4];
int [] b = a;

Але треба мати на увазі, що змінні a і b вказують на один і той же масив. Спочатку це може збивати з пантелику, але якщо пам'ятати що ми маємо справу з посилальними типами даних, то все стає на свої місця. Якщо цей момент не зрозумілий, то трохи пізніше ми все це розберемо на прикладах.

Слід, так само, ще раз згадати, що посиланням (змінної масиву) можна привласнити "порожнє" значення null, що не вказує ні на яку адресу оперативної пам'яті:

a

= Null;

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

Розмір або довжину масиву можна отримати за допомогою константи length, яка визначена для кожного масиву і повертає його довжину. Ми їй уже не раз користувалися в прикладах коли працювали з аргументами переданої в командному рядку.

Можна створювати та використовувати масиви нульової довжини (порожній масив). наприклад:

boolean

[] Bits = new boolean [0];

Ініціалізувати такий масив не можна, так як у нього просто немає елементів які можна форматувати. Відразу ж виникає питання, а на кой ляд вони тоді взагалі потрібні ці порожні масиви? Але вони потрібні і навіть дуже корисні!

Порожній масив прийнято використати в тих місцях програми, де заздалегідь невідомо, будуть елементи чи ні. Якщо елементи будуть, то повертається непорожній масив, якщо елементів немає - порожній масив. Прикладом може служити масив рядків який передається в метод main () і містить аргументи командного рядка, а якщо їх немає, то повертається порожній масив.

Порожній масив краще, ніж null, бо не вимагає окремого if'а для обробки. Те ж вірно для списків і інших колекцій. Саме тому існують методи Collections.emptyList, emptySet, emptyMap.

Ініціалізація (initialization) масиву

На цьому етапі елементи масиву отримують початкові значення. Ініціалізувати елементи масиву значеннями можна декількома способами:

  1. Присвоїти кожному елементу масиву конкретне значення (це можна зробити наприклад в циклі, але до цього масив вже повинен бути оголошений і створений)
  2. Ініціалізувати масив за допомогою перерахування значень його елементів в фігурних дужках (це можна зробити як на етапі оголошення, так і на етапі створення, але синтаксис при цьому різний)

Звертається до конкретного елементу масиву можна по його індексу, який починається з нуля, як це вже говорилося.

Індекси можна задавати будь-якими цілочисельними виразами, крім типу long, наприклад a [i + j], a [i% 5], a [++ i]. Виконуюча система Java стежить за тим, щоб значення цих виразів не виходили за межі довжини масиву. Якщо ж вихід все ж станеться інтерпретатор Java в такому випадку припинить виконання програми і виведе на консоль повідомлення про вихід індексу масиву за кордону його визначення (ArrayIndexOutOfBoundsException).

Розглянемо приклад першого способу ініціалізації:

int

[] Ar = new int [2];
ar [0] = 1;
ar [1] = 2;

Другий спосіб ініціалізації можна реалізувати по різному.

Ініціалізацію масиву можна поєднати до етапу створення, але до цієї операції масив вже повинен бути оголошений. наприклад:

int

[] Ar; // оголошення масиву
ar = new int [] {назад 1, 2}; // створення і ініціалізація

До створення і ініціалізації масиву ar він вже був оголошений.

Так само форматувати масив можна на етапі його оголошення наступним синтаксисом:

int

[] Ar = {1, 2}; // оголошення, створення і ініціалізація масиву

Увага! Цей синтаксис ініціалізації масиву працює тільки при оголошенні масиву і поєднує відразу всі три операції оголошення, створення і ініціалізацію. Якщо масив вже оголошений, то такий синтаксис використовувати не можна. Компілятор видасть помилку. Тобто:

int [] ar; // оголошення масиву
ar = {1, 2}; // ПОМИЛКА !!! створення і ініціалізація масиву

Таке дійство не пройде.

Так само можна форматувати на етапі оголошення і чуть чуть по іншому:

int

[] Ar = new int [] {1, 2}; // оголошення, створення і ініціалізація

Хоча цей синтаксис довший. Якщо ви помітили, то даний синтаксис це теж поєднання всіх трьох операцій: оголошення, створення і ініціалізації.

В Java передбачений синтаксис, який підтримує анонімні масиви (вони не присвоюються змінним і, отже, у них немає імен). Іноді масив потрібно задіяти лише один раз (наприклад, передати його методу), отже, ви не хочете витрачати час на присвоювання його змінної, тому можна відразу ж використовувати результат оператора new. наприклад:

System

. out. println (new char [] { 'H', 'e', 'l', 'l', 'o'});

Синтаксис ініціалізації масивів за допомогою фігурних дужок називається літерально, оскільки для ініціалізації використовується масив-літерал.

Важливо розуміти що масиви-літерали створюються і не започатковано під час виконання програми, а не під час її компіляції. Розглянемо наступний масив-літерал:

int

[] PerfectNumbers = {6, 28};

Він компілюється в такий байт-код Java:

int

[] PerfectNumbers = new int [2];
perfectNumbers [0] = 6;
perfectNumbers [1] = 28;

Тому якщо вам потрібно розмістити в Java програмі багато даних, краще не включати їх безпосередньо в масив, оскільки компілятор Java доведеться створювати багато байткод ініціалізації масиву, а потім інтерпретатора Java потрібно буде ретельно виконувати весь цей код. У таких випадках краще зберігати дані в зовнішньому файлі і зчитувати їх в програму під час її виконання.

Однак той факт, що Java ініціалізує масив під час виконання програми, має важливі наслідки. Це означає, що елементи масиву-литерала є будь-якими виразами, що обчислюються під час виконання програми, а не постійними виразами, що обчислюються компілятором. наприклад:

Point

[] Points = {circle1.getCenterPoint (), circle2.getCenterPoint ()};

Тепер трошки попрактікуемся.

У добре нам відомому методі main (), як раз і використовується можливість повернення масиву нульової довжини якщо в командному рядку немає аргументів, що дозволяє уникнути використання оператора if для перевірки на null, щоб уникнути помилки під час виконання програми.

Тобто ми відразу можемо використовувати масив в циклі, правда дотримуючись правил щоб не вийти за межі максимального індексу.

На початку програми ми виводимо значення довжини масиву, а потім в першому циклі послідовно виводимо всі значення елементів масиву. Другий цикл робить те ж саме, але збоченим способом.

Другий приклад я привіт щоб порадувати ваш мозок розширити вашу свідомість вам не було нудно знали якомога робити, але як не потрібно, ну і чисто в навчально-освітніх цілях. Може на дозвіллі розберетеся як працює другий цикл.

Дана програма генерує наступний висновок:

У першому випадку ми не вводили ніяких аргументів, тому отримали масив нульової довжини, який не був оброблений в циклах, оскільки не задовольняє умовам циклів.

У другому випадку ми передали аргументи в командному рядку і отже масив був оброблений в циклах.

Відразу ж виникає питання, а на кой ляд вони тоді взагалі потрібні ці порожні масиви?

Новости