Оголошення final і static-JAVA ДЛЯ ANDROID

&nbsp

У мові Java існує 11 ключових слів-модифікаторів, які можуть застосовуватися до оголошення Ці модифікатори змінюють поведінку оголошеного обєкта, іноді досить істотно У попередніх прикладах деякі модифікатори, наприклад publіс і private, вже використовувалися без пояснень Ці, а також деякі інші модифікатори управляють областями дії і видимості Далі ми розглянемо їх детальніше У даному розділі ми поговоримо ще про два модифікаторах, важливих для повного розуміння системи типів Java: final і static

Оголошення з ключовим словом final не може бути змінено Класи, методи, поля, параметри і локальні змінні – всі вони можуть бути final

Стосовно до класу final означає, що будь-яка спроба визначити підклас викличе помилку Наприклад, клас String є final, оскільки рядки повинні бути постійними (це значить, що після того, як рядок створена, її зміст має залишатися незмінним) Трохи поміркувавши над цією ситуацією, приходимо до висновку, що виконання такої умови можна гарантувати лише у випадку, якщо від Stri ng не зможуть утворюватися підтипи Якби від класу String можна було утворювати підтипи, то якась підступна бібліотека могла б створити підклас String – DeadlyString, – передати його примірник в ваш код і змінити його значення з fred на DROP TABLE (Проілюстрована спроба впровадження в ваш код чужорідного SQL, який здатний видалити частини бази даних) Це могло б статися відразу після того, як ваш код проведе перевірку (валідацію) вмісту цього рядка

Стосовно до методу final означає, що даний метод не може бути перевизначений в підкласі Розробники використовують final-методи для проектування спадкування, коли супертіп повинен повідомити підкласу поведінку, яка сильно залежить від конкретної реалізації, і супертіп не може дозволити, щоб це поведінка змінювалося Фреймворк, в якому реалізований універсальний (generic) кеш, може визначити базовий клас під назвою, наприклад, CacheableObject Програміст, який використовує фреймворк, створює підтип цього класу для кожного нового кешувального типу обєкта Однак для підтримки цілісності фреймворка класу Cacheabl eObject може знадобитися розрахувати ключ кешу, який повинен бути однаковим в обєктах будь-яких типів У даному випадку метод computeCacheKey може бути оголошений як final

Стосовно до змінної – полю, параметру або локальної змінної – final означає, що значення присвоюється змінної тільки один раз і після цього більше не змінюється Дане обмеження додатково посилюється компілятором: мало того, що значення не змінюється, компілятор також повинен мати можливість переконатися, що воно в принципі не може бути змінено У випадку з полем це означає, що значення повинно присвоюватися або в рамках оголошення, або в кожному конструкторі Якщо не вдасться ініціалізувати поле final в рамках оголошення або в конструкторі або при спробі присвоєння значення де-небудь ще, виникне помилка

У випадку з параметрами final означає, що в рамках методу параметр завжди має тільки те значення, яке було передано при виклику Спроба присвоєння параметра з модифікатором final викличе помилку Зрозуміло, оскільки значення параметра в більшості випадків є посиланням на той чи інший обєкт, існує можливість, що обєкт зміниться Застосування ключового слова final до параметру просто означає, що цей параметр не може бути заново присвоєний

Мінлива final може бути присвоєна не більше одного разу Оскільки використання змінної без ініціалізації також є помилкою, в мові Java мінлива final присвоюється тільки один раз без винятків Присвоєння може здійснюватися де завгодно в рамках зовнішнього (вищестоящого) блоку перед використанням

Оголошення static відноситься до класу, в якому воно описується, а не до примірника цього класу, static – це модифікатор «статичності», протилежний «динамічності» Мається на увазі, що, якщо сутність не оголошена як статична, вона є динамічною Проілюструємо це на прикладі:

У даному прикладі QuietStatic – це імя класу, а ех – посилання на екземпляр цього класу Статичний член classMember – це атрибут класу Щоб послатися на нього, його потрібно просто кваліфікувати імям класу З іншого боку, іnstanceMember є членом екземпляра класу Спроба послатися на нього через посилання класу викличе помилку І це можна пояснити Існує багато різних змінних з назвою іnstanceMember, і кожна з них відноситься до окремого екземпляру QuietStatic Якщо явно не вказати ту змінну, про яку ви говорите, Java не зможе зрозуміти, яка з цих змінних мається на увазі

Як видно з другої пари тверджень, Java насправді допускає посилання на (статичні) змінні класу через посилання на екземпляр Але така практика не вітається, оскільки призводить до плутанини У більшості компіляторів та інтегрованих середовищ розробки ви отримаєте попередження, якщо спробуєте зробити щось подібне

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

І його висновок:

Вихідним значенням змінної elassMember в попередньому прикладі є 0 Воно збільшується на 1 кожним з двох окремих примірників Тепер обидва примірники бачать нового значення – 2 Значення змінної instanceMember також починається з 0 в кожному примірнику З іншого боку, кожен екземпляр виконує прирощення своєї копії і переглядає значення власної змінної, рівне 1

Статичні визначення класів і методів подібні в тому, що в обох випадках статичний обєкт бачимо за своїм кваліфікованому імені, а динамічний обєкт бачимо тільки за посиланням на екземпляр Але, крім подібності, існують і набагато більш неочевидні відмінності

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

У сучасній мові Java практично недоцільно використовувати статичні методи У ранніх реалізаціях Java динамічне призначення методів протікало значно повільніше, ніж статичне Розробники воліли користуватися статичними методами для оптимізації коду В Android, де середовище Dalvik забезпечує динамічну компіляцію, в оптимізації такого роду більше немає потреби Надмірне використання статичних методів зазвичай вважається ознакою неякісної архітектури

Різниця між статично і динамічно оголошеними класами особливо тонка: Більшість класів, з яких складається додаток, є статичними Як правило, клас визначається на верхньому рівні – За межами зовнішнього блоку Передбачається, що всі такі оголошення мають бути статичними З іншого боку, більшість інших оголошень відбувається всередині зовнішнього блоку певного класу, тобто за умовчанням вони є динамічними У той час як більшість полів за замовчуванням є динамічними і вимагають модифікатора, щоб стати статичними, більшість класів відразу є статичними

Насправді система дуже струнка Згідно з тим, як ми визначили ознака statiс – приналежність до класу, а не до примірника цього класу, – оголошення верхнього рівня повинні бути статичними (оскільки вони не відносяться ні до якого класу) Однак при оголошенні всередині зовнішнього блоку, наприклад всередині класу верхнього рівня, визначення класу за замовчуванням також стає динамічним Щоб створити динамічно оголошений клас, просто визначте його всередині якого-небудь іншого класу

Ми підійшли до різниці між статичним і динамічним класами Динамічний клас має доступ до членів примірника вищестоящого класу (так як ставиться до цього примірника) Статичний Кларс – не має Ось приклад коду:

Трохи поміркуйте – і відразу зрозумієте, що тут відбувається Поле х – це член екземпляра класу Outer Іншими словами, існує безліч змінних х, по одній для кожного екземпляра часу виконання (Runtime instance) класу Outer Клас InnerTube входить до складу класу Outer, але не будь-якого екземпляра класу Outer Він ніяк не може ідентифікувати х З іншого боку, клас InnerOne відноситься до примірника Outer, оскільки є динамічним Можна уявити, що тут ми маємо окремий клас InnerOne для кожного екземпляра Outer (хоча фактично це не так) Отже, InnerOne має доступ до членів того примірника Outer, до якого цей InnerOne відноситься

OuterTest дозволяє переконатися, що, як і з полями, можна використовувати статичну внутрішнє визначення (в даному випадку – створити зразок класу), просто скориставшись його класифікованих імям Однак динамічне визначення корисно тільки в контексті екземпляра

Джерело: Android Програмування на Java для нового покоління мобільних пристроїв

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*