Інтернет Windows Android

Які модифікатори доступу існують в java. модифікатори доступу

Тут ми постараємося розглянути майже всі випадки застосування модифікаторів доступу. Виняток становитимуть лише їх застосування для вкладених ( nested) І внутрішніх ( inner) Класів, а так само для інтерфейсів, так як ці теми ми ще поки не розглядали.

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

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

  • public- будь-який компонент, оголошений як public, Доступний з будь-якого коду
  • protected- надати їм доступ до компоненту в межах пакету і класам спадкоємцям
  • private- надати їм доступ до компоненти в межах класу
  • за замовчуванням(Немає ключового слова) - дозволяє доступ до компонентів в межах пакету

Класи спадкоємці - це класи успадковані від будь-якого класу. Спадкування ми поки ще не вивчали.

Доступ до класів

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

Доступ до членів класу

Члени класу завжди доступні всередині тіла класу. За замовчуваннямчлени класу також доступні в пакеті, в якому клас визначено.

модифікатор public

Для класу, який не є вкладеним, може бути зазначений тільки один з двох можливих рівнів доступу: заданий за замовчуваннямі public . Коли клас оголошений як public, Він повинен бути єдиним publicкласом, оголошеним в файлі, і ім'я файлу повинна відповідати імені класу.

як publicможуть бути оголошені класи, поля, методи і конструктори.

модифікатор protected

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

Єдино що зараз можна коротко сказати, що до компонентів оголошеним як protected, Буде мати доступ будь-який дочірній клас з будь-якого пакетаабо будь-який клас з того ж пакета.

як protectedможуть бути оголошені поля, методи, конструктори, вкладені класи і вкладені інтерфейси.

protected .

модифікатор private

Це найжорсткіший щодо обмеження доступу модифікатор. Елементи оголошені як privateдоступні тільки всередині цього ж класу і ні кому поза класом.

як privateможуть бути оголошені поля, методи, конструктори, вкладені класи і вкладені інтрефеси.

Класи і інтерфейси верхнього рівня не можуть бути оголошені як private .

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

Я створив класи Mod02.java, DefMod.java, ProMod.java і PrvMod.java які належать пакету pro.java.pkg002, а так же клас PubMod.java, що належить пакету pro.java.pkg003. Далі приведу просто скріни цих класів і результат роботи програми:

Ми поговоримо про модифікатори: які бувають модифікатори, області видимості, модифікатори для класів, полів, методів. Думаю, буде не нудно.

Модифікатори в Java- це ключові слова, які надають класу, полю класу або методом певні властивості.

Для позначення видимості класу його методів і полів є 4 модифікатора доступу:

  • privateчлени класу доступні тільки усередині класу;
  • package-private або default (за замовчуванням)члени класу видно всередині пакету;
  • protectedчлени класу доступні всередині пакету і в класах-спадкоємців;
  • publicчлени класу доступні всім.

Якщо Ви пам'ятаєте, то в кінці, коли ми вже імпортували клас Cat, у нас все одно була помилка компіляції.

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

Ви можете почати шукати відповіді на запитання: а для чого все це потрібно? Чому не зробити видимість коду з будь-якого пакета або класу, а потрібно розмежувати доступ? Ці питання самі пропадуть, коли прийде час писати складні і громіздкі проекти. Зараз, коли ми пишемо додатки, у яких функціонал обмежений одним або двома класами, то сенсу що або обмежити ніби як не видно.

Уявіть, що у Вас є клас який відображає об'єкт якогось продукту. Наприклад машина. У машини може бути ціна. Ви створили поле ціна і ще безліч інших полів, купу методів які відповідають за функціонал. Все ніби добре. Ваш клас машина є частиною величезного проекту і всі задоволені. Але припустимо, що хтось помилково або спеціально створив екземпляр класу автомобіль і поставив негативну ціну. Хіба може товар мати негативну ціну? Це дуже примітивний приклад і навряд чи таке може трапитися в реальному житті, але думаю, ідея зрозуміла. Іноді потрібно дати доступ не безпосередньо, а через певні методи. Може бути, що код відповідає за функціонал іншого коду, і Ви не хочете, щоб хтось змінював і редагував частина Вашої. Для цього всього і є обмеження доступу.

Модифікатор доступу у конструкторів, методів і полів може бути будь-хто. Клас може бути тільки або public, або default, причому в одному файлі може перебувати тільки один public клас.

Поки про модифікатори доступу буде досить. У статті «Об'єктно орієнтоване програмування» ми про них поговоримо докладніше, а зараз давайте поговоримо про інші модифікатори яких, до речі, чимало.

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

static модифікатор перед методом або полем говорить про те, що вони не належать до примірника даного класу. Що це означає для нас? Коли ми описали поле класу або метод як static, його можна викликати без використання екземпляра класу. Тобто замість такої конструкції: Cat cat = new Cat (); cat.method (), можна написати просто Cat.method (). За умови, що метод оголошений як static. Статичні змінні єдині для всіх об'єктів класу. У них одне посилання.

    public class Modificators (

    static int anotherStaticField = 5;

    public static void myStaticMethod () (

    someField = "My field";

    // nonStaticField = ""; помилка компіляції

    // не можна використовувати нестатичні поля

    // в статичних методах

    public void myNonStaticMethod () (

    anotherStaticField = 4; // стітіческіе поля можна використовувати

    // в нестатичних методах

    // main метод теж має модифікатор static

    new Modificators () .myNonStaticMethod ();

    Modificators.myStaticMethod (); // виклик статичних методів і полів

    // через імяКласса.метод

Ще одне важливе зауваження, яке потрібно сказати з приводу static модифікаторів: статичні поля не започатковано під час завантаження класу. Часто в різного роду тестах по Java можна зустріти такий код:

Питання: що буде виведено на консоль? Потрібно пам'ятати, що static блок буде виведений першим при будь-якому розкладі. Далі буде йти блок за замовчуванням. Далі дивіться на скрін консолі:

Наступний модифікатор, який ми розглянемо буде final.

Думаю, слово final говорить сама за себе. Застосовуючи final модифікатор Ви говорите, що поля не можуть бути змінені, методи перевизначені, а класи можна успадковувати (про спадкування буде окрема стаття). Цей модифікатор застосовується тільки до класів, методам і змінним (також і до локальних змінних).

З модифікатором final до методів і класів ми будемо говорити в статті ООП.

Далі підуть модифікатори, які новачкам або читає даний цикл статей з нуля будуть не дуже зрозумілими. І хоча я поки не зможу Вам все пояснити (в силу того, що Ви не знаєте супутнього матеріалу), все ж раджу просто ознайомитися з ними. Коли прийде час використання даних модифікаторів, Ви вже будете розуміти більшість термінів використовуваних нижче.

модифікатор synchronized- говорить про те, що метод може бути використаний тільки одним потоком одночасно. Хоча, можливо, це Вам ні про що не говорить, корисність цього модифікатора буде видно, коли ми будемо вивчати многопоточность.

модифікатор transient- говорить про те, що під час сериализации об'єкта деяке поле потрібно ігнорувати. Як правило, такі поля зберігають проміжні значення.

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

модифікатор nativeперед оголошенням методу вказує що метод написаний іншою мовою програмування. Зазвичай на мові C.

модифікатор strictfp- Забезпечує виконання операцій над числами типу float і double (з плаваючою комою) за стандартом IEEE 754. Або кажучи простіше, гарантує що в межах методу результати обчислень будуть однаковими на всіх платформах.

Я ще не говорив про модификаторе abstract. Про нього скажу коротко, так як без знань основ об'єктно орієнтованого програмування говорити про нього не бачу сенсу.

Клас, який має модифікатор abstract не може створити екземпляр. Єдина мета для нього бути розширеним. Клас abstract може містити як абстрактні методи, а також і звичайні.

Детальніше про модификаторе abstract будемо говорити в статті ООП.

На цьому можна і закінчити статтю про модифікатори. Багато що про них не було сказано. Але це через те, що у нас ще немає понять ООП. Через кілька статей, ми доповнимо знання про модифікатори і заповнимо прогалини.

Які Ви додаєте при ініціалізації для зміни значень. Мова Java має широкий спектр модифікаторів, основні з них:

  • модифікатори доступу;
  • модифікатори класу, методу, змінної і потоку, які використовуються не для доступу.

Щоб використовувати модифікатор в Java, потрібно включити його ключове слово в визначення класу, методу або змінною. Модифікатор повинен бути попереду решти оператора, як показано в наступних прикладах:

Public class className (// ...) private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main (String arguments) (// тіло методу)

модифікатори доступу

Java надає ряд модифікаторів доступу, щоб задати рівні доступу для класів, змінних, методів і конструкторів. Існує чотири доступу:

  • Відомий в пакеті (стоїть за умовчанням і модифікатор не потрібні).
  • Відомий тільки для класу (private).
  • Відомий для всіх (public).
  • Відомий для пакета і всіх підкласів (protected).

Модифікатор доступу за замовчуванням - без ключового слова

Модифікатор доступу за замовчуванням- означає, що ми явно не оголошуємо модифікатор доступу в Java для класу, поля, методу і т.д.

Мінлива чи метод, оголошені без модифікатора контролю доступу доступні для будь-якого іншого класу в тому ж пакеті. Поля в інтерфейсі неявно є public, static, final, а методи в інтерфейсі за замовчуванням є public.

приклад

Змінні і методи можуть бути оголошені в Java без будь-яких модифікаторів, як показано в наступному прикладі:

String version = "1.5.1"; boolean processOrder () (return true;)

Модифікатор доступу private

модифікатор private- методи, змінні і конструктори, які оголошені як private в Java можуть бути доступні тільки в межах самого оголошеного класу.

Модифікатор доступу private є найбільш обмежуючим уровенем доступу. Клас і інтерфейси не можуть бути private.

Змінні, оголошені як private, можуть бути доступні поза класом, якщо отримують їх відкриті (public) методи присутні в класі (нижче дивіться приклад і пояснення).

Використання модифікатора private в Java є основним способом, щоб приховати дані.

приклад

Наступний клас використовує контроль доступу private:

Public class Logger (private String format; public String getFormat () (return this.format;) public void setFormat (String format) (this.format = format;))

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

Таким чином, щоб ця змінна була доступна для всього, ми визначили два відкритих (public) методи: getFormat (), Який повертає значення format, і setFormat (String), Який встановлює її значення.

Модифікатор доступу public

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

Проте, якщо до public класу в іншому пакеті ми намагаємося отримати доступ, то public клас доводиться імпортувати.

Завдяки спадкоємства класів, в Java все публічні (public) методи і змінні класу успадковуються його підкласами.

приклад

Наступна функція використовує контроль доступу public:

Public static void main (String arguments) (// ...)

метод main ()повинен бути публічним (public). В іншому випадку, він не може бути викликаний за допомогою java-інтерпретатора, щоб запустити клас.

Модифікатор доступу protected

модифікатор protected- змінні, методи і конструктори, які оголошуються як protected в суперкласі, можуть бути доступні тільки для підкласів в іншому пакеті або для будь-якого класу в пакеті класу protected.

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

Доступ protected дає підкласу можливість використовувати допоміжний метод або змінну, запобігаючи неспоріднених клас від спроб використовувати їх.

приклад

Наступний батьківський клас використовує контролю доступу protected, щоб його дочірній клас перевизначив метод openSpeaker ():

Class AudioPlayer (protected boolean openSpeaker (Speaker sp) (// деталі реалізації)) class StreamingAudioPlayer (boolean openSpeaker (Speaker sp) (// деталі реалізації))

При цьому, якщо ми визначимо метод openSpeaker ()як protected, то він не буде доступний з будь-якого іншого класу, крім AudioPlayer. Якщо ми визначимо його як public, то він стане доступним всім. Але наш намір полягає в тому, щоб розкрити цей метод тільки підкласу, ось чому ми використовували модифікатор protected.

Правила контролю доступу та успадкування

Наступні правила в Java застосовуються для успадкованих методів:

  • Методи, оголошені як public в суперкласі, також повинні бути public у всіх підкласах.
  • Методи, оголошені як protected в суперкласі, повинні або бути або protected, або public в підкласах; вони не можуть бути private.
  • Методи, оголошені як private для всіх не успадковуються, так що немає ніякого правила для них.

Модифікатори класу, методу, змінної і потоку, які використовуються не для доступу

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

  • модифікатор staticзастосовується для створення методів і змінних класу;
  • модифікатор finalвикористовується для завершення реалізації класів, методів і змінних;
  • модифікатор abstractнеобхідний для створення абстрактних класів і методів;
  • модифікатори synchronizedі volatileвикористовуються в Java для потоків.

модифікатор static

модифікатор static- застосовується для створення методів і змінних класу.

змінні static

Ключове слово static використовується для створення змінних, які будуть існувати незалежно від будь-яких примірників, створених для класу. Тільки одна копія змінної static в Java існує незалежно від кількості примірників класу.

Статичні змінні також відомі як змінні класу. В Java локальні змінні не можуть бути оголошені статичними (static).

методи static

Ключове слово static використовується для створення методів, які будуть існувати незалежно від будь-яких примірників, створених для класу.

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

Змінні і методи класу можуть бути доступні з використанням імені класу, за яким слідує крапка і ім'я змінної або методу.

приклад

Модифікатор static в Java використовується для створення методів класів і змінних, як показано в наступному прикладі:

Public class InstanceCounter (private static int numInstances = 0; protected static int getCount () (return numInstances;) private static void addInstance () (numInstances ++;) InstanceCounter () (InstanceCounter.addInstance ();) public static void main (String arguments ) (System.out.println ( "Починаючи з" + InstanceCounter.getCount () + "екземпляра"); for (int i = 0; i

Буде отримано наступний результат:

Починаючи з 0 примірника Створено 500 примірників

модифікатор final

модифікатор final- використовується для завершення реалізації класів, методів і змінних.

змінні final

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

Однак дані всередині об'єкта можуть бути змінені. Таким чином, стан об'єкта може бути змінено, але не посилання.

Зі змінними в Java модифікатор final часто використовується з static, щоб зробити константою змінну класу.

приклад

public class Test (final int value = 10; // Нижче наведені приклади оголошення констант: public static final int BOXWIDTH = 6; static final String TITLE = "(! LANG: Менеджер"; public void changeValue(){ value = 12; //будет получена ошибка } } !}

методи final

Метод final не може бути перевизначений будь-яким подклассом. Як згадувалося раніше, в Java модифікатор final запобігає метод від змін в підкласі.

Головним намір зробити метод final буде те, що зміст методу не повинно бути змінено стороні.

приклад

Оголошення методу, що використовує модифікатор final в оголошення класу, показано в наступному прикладі:

Public class Test (public final void changeName () (// тіло методу))

клас final

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

приклад

public final class Test (// тіло класу)

модифікатор abstract

модифікатор abstract- використовується для створення абстрактних класів і методів.

клас abstract

Клас abstract не може створити екземпляр. Якщо клас оголошений як abstract, то єдина мета для нього бути розширеним.

Клас не може бути одночасно abstract і final, так як клас final не може бути розширеним. Якщо клас містить абстрактні методи, то він повинен бути оголошений як abstract. В іншому випадку буде згенеровано помилка компіляції.

Клас abstract може містити як абстрактні методи, а також і звичайні.

приклад

abstract class Caravan (private double price; private String model; private String year; public abstract void goFast (); // абстрактний метод public abstract void changeColor ();)

метод abstract

Метод abstract є методом, оголошеним з будь реалізацією. Тіло методу (реалізація) забезпечується подклассом. Методи abstract ніколи не можуть бути final або strict.

Будь-клас, який розширює абстрактний клас повинен реалізувати всі абстрактні методи суперкласу, якщо підклас не є абстрактним класом.

Якщо клас в Java містить один або кілька абстрактних методів, то клас повинен бути оголошений як abstract. Абстрактний клас не зобов'язаний утримувати абстрактні методи.

Абстрактний метод закінчується крапкою з комою. Приклад: public abstract sample ();

приклад

public abstract class SuperClass (abstract void m (); // абстрактний метод) class SubClass extends SuperClass (// реалізує абстрактний метод void m () (.........))

модифікатор synchronized

модифікатор synchronized

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

приклад

public synchronized void showDetails () (.......)

модифікатор transient

Мінлива примірника зазначена як transient вказує віртуальній машині Java (JVM), щоб пропустити певну змінну при серіалізациі об'єкта, що містить її.

Цей модифікатор включений в оператор, що створює змінну, що передує класу або типу даних змінної.

приклад

public transient int limit = 55; // НЕ буде зберігатися public int b; // буде зберігатися

модифікатор volatile

модифікатор volatile- використовуються в Java для потоків.

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

Доступ до змінної volatile синхронізує всі кешированниє скопійовані змінні в оперативній пам'яті. Volatile може бути застосований лише до змінних екземпляра, які мають тип об'єкт або private. Посилання на об'єкт volatile може бути null.

приклад

public class MyRunnable implements Runnable (private volatile boolean active; public void run () (active = true; while (active) (// лінія 1 // тут який-небудь код)) public void stop () (active = false; / / лінія 2))

Як правило, run () викликається в одному потоці (вперше починаєте використовувати Runnable в Java), а stop () викликається з іншого потоку. Якщо в лінії 1 використовується кешований значення active, то цикл не може зупинитися, поки Ви не встановите active false в лінії 2.

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

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

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

  • private (закритий)
  • public (відкритий)
  • protected (захищений)
  • доступ за замовчуванням, коли ніякої модифікатор не присутній

Приклади оголошення модифікаторів (він завжди повинен бути першим):

Public int i; private double j, k; private int createMethod (int a) (...); public class Cat ()

Як бачите, модифікатор застосуємо до змінної, методом, класу.

public

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

Припустимо, що клас оголошений як public, І в ньому є два методи. Один private, Другий - public. У вас буде доступ до класу і до другогометоду, але не до першого, незважаючи на те, що сам клас відкритий.

private

Ключове слово privateозначає, що доступ до члена класу не надається нікому, крім методів цього класу. Інші класи того ж пакета також не можуть звертатися до private-членам.

Всі допоміжні методи класів варто оголосити як private, Щоб запобігти їх випадкові виклики в пакеті. Теж відноситься і до private-полів всередині класу.

protected

Ключове слово protectedпов'язане з поняттям спадкування, при якому до вже існуючого класу (базового) додаються нові члени, причому вихідна реалізація залишається незмінною. Також можна змінювати поведінку вже існуючих членів класу. Для створення нового класу на базі існуючого використовується ключове слово extends.

Якщо при створенні нового пакета використовується успадкування від класу, що знаходиться в іншому пакеті, новий клас отримує доступ тільки до відкритих (public) членам з вихідного пакета. Іноді творцеві базового класу необхідно надати доступ до конкретного методу похідним класам, але закрити його від всіх інших. У цих випадках використовується ключове слово protected. специфікатор protectedтакож надає доступ в межах пакету, тобто члени з цим специфікатором доступні для інших класів з того ж пакета.

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

Розглянемо вигаданий клас SillySensor

Public class SillySensor (private int sensorData; public SillySensor () (sensorData = 0;) private void calibrate (int iSeed) (// код для калібрування) protected void seedCalibration (int iSeed) (calibrate (iSeed);) public int getSensorData ( ) (// Check sensor here return sensorData;))

Клас оголошений як publicі доступний в інших класах. У класу є змінна sensorData, Яка доступна тільки в своєму класі (private). Конструктор доступний в інших класах ( public). метод calibrate ()працює тільки всередині класу ( private). метод seedCalibration ()доступний в своєму класі або в підкласі ( protected). метод getSensorData ()доступний в інших класах ( public).

клас Modifier
Клас Modifier кодує всі модифікатори,
використовувані в оголошеннях типу, у вигляді
констант:
ABSTRACT, FINAL, INTERFACE, NATIVE,
PRIVATE, PROTECTED, PUBLIC, STATIC,
STRICT, SYBCHRONIZED, TRANSIDENT,
VOLATILE.
Кожній з констант відповідає метод запит виду
isMod (int modifier) ​​(тут Mod одне з вище
наведених імен, наприклад, isPublic),
який повертає true, якщо модифікатор
mod присутній в оголошенні типу.

Розглянемо приклад. нехай є
оголошення поля
public static final int s = 10;
тоді значення, що повертається методом
getModifiers відповідного об'єкта
класу Field матиме вигляд
Modifier.PUBLIC | Modifier.STATIC |
Modifier.FINAL
Модифікатор strictfp представляється
константою STRICT.
Методи-запити можна використовувати в
такою формою

Modifier.isPrivate (field.getModifiers ());
це еквівалентно такій умові
(Field.getModifiers () & Modifier.PRIVATE)! = 0
клас Field
У складі класу Field реалізовані методи,
дозволяють запитувати інформацію про
типі поля, а також зчитувати і задавати його
значення.
Розглянемо деякі методи класу Field
1. getType () - повертає об'єкт класу
Class, який відповідає типу поточного поля.
Наприклад, для поля типу int, отримаємо
int.class.

2. Методи set і get - дозволяють зчитувати
поточне значення поля, а також задавати нове.
Розглянемо приклад:
public static void printField (Object o,
String name) throws
NoSuchFieldException,
IllegalAccessException (
Field field = o.getClass (). GetField (name);
Short value = (Short) field.get (o);
System.out.println (value);
}
Тобто метод get повертає значення, на яке
посилається відповідне поле або об'єкт
класу -оболонки.
Приклад використання методу set має вигляд:

public static void setField (Object o, String name,
short nv) throws
NoSuchFieldException,
IllegalAccessException (
Field field = o.getClass (). GetField (name);
field.set (o, new Short (nv));
}
Для збереження nv в поле даного об'єкта
необхідно використовувати класи оболонки.
Існують також методи мають вигляд
getPrimitiveType (наприклад, getInt) і
setPrimitiveType. Ці методи можна
використовувати для зміни полів у класі,
мають примітивний тип. наприклад,
field.setShort (o, nv);

клас Method
Засоби класу Method - дозволяють отримувати
повну інформацію, що стосується
оголошень методів певного класу,
і при необхідності викликати ці методи в
контексті заданих об'єктів.
Розглянемо методи класу Method.
1. public Class getReturnType () - повертає
об'єкт Class, який відповідає типу
значення, що повертається поточним методом.
Якщо замість типу значення, що повертається в
оголошенні методу вказано службове
слово void, що розглядається метод поверне
об'єкт void.class.

2. public Class getParameterTypes () - повертає

параметрів, які задані в оголошенні
поточного методу. Об'єкти заносяться в масив в
тому порядку, в якому параметри перераховані в
оголошенні методу. Якщо метод не має
параметрів, повертається порожній масив.
3. public Class getExceptionTypes () - повертає
масив об'єктів Class, відповідних типів
винятків, які задані в реченні
throws оголошення поточного методу. об'єкти
заносяться в масив в тому порядку, в якому
найменування типів виключень перераховані в
оголошенні методу.

4. public Object invoke (Object onThis, Object args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
Викликає метод, який визначається поточним об'єктом
Method, в контексті об'єкта onThis із завданням
значень аргументів, переданих масивом args.
Для нестатичних методів вибір реалізації
здійснюється на підставі фактичного типу
об'єкта, що визначається параметром onThis. для
статичних методів onThis не приймається до
увагу і може дорівнювати null.
Довжина масиву args повинна збігатися з числом
параметрів в оголошенні методу, а типи об'ектовелементов масиву повинні допускати присвоювання
відповідним типам параметрів методу - в
Інакше буде викинуто виключення
IIlegalArgumentException.

10.

Якщо в складі об'єкта, що визначається
параметром onThis, немає типу, членом
якого є поточний метод,
викидається виключення
IllegalArgumentException.
Якщо значення onThis одно null і метод не
статичний, генерується виключення типу
NullPointerException.
Якщо виконання викликається методу
завершується аварійно, викидається
виключення типу InvocationTargetException.

11.

Розглянемо приклад. викличемо засобами
рефлексії метод return str.indexOf ( ".", 8)
тоді маємо
try (
Сlass strClass = str.getClass ();
Method indexM = strClass.getMethod ( "indexOf",
new Class (string.class, int.class));
Object result = indexM.invoke (str, new object (
".", New lnteger (8)));
return ((Integer) result) .intValue ();
}
catch (NoSuchMethodException e) (...... ..)
catch (invocationTargetException e) (...... ..)
catch (illegalAccessException e) (......)

12.

клас Constructor
Для створення нових екземплярів (об'єктів)
типу може бути використаний метод
newlnstance об'єкта Class,
відповідного цього типу.
Метод викликає конструктор без аргументів,
що належить типу, і повертає посилання
на новостворений об'єкт класу Object,
який повинен бути явно перетворений до
необхідному типу.
Розглянемо приклад.

13.

static double testData = (0.3,1.3e-2, 7.9, 3.17);

try (
for (int arg = 0; arg< args.length; arg++){
String name = args;
Class classFor = Class.forName (name);
SortDouble sorter =
(SortDouble) classFor.newInstance ();
SortMetrics metrics = sorter.sort (testData);
System.out.println (name + ":" + metrics);
for (int i = 0; i< testData.length; i++)
System.out.println ( "" + testData [i]);))
catch (Exception e) (System.err.println (e);))

14.

Метод newlnstance при некоректному
застосуванні здатний викидати велику
число об'єктів винятків різних
типів.
InstantiationException-якщо клас, об'єкт
якого повинен бути створений, не володіє
конструктором без аргументів, або
визначений як абстрактний, або в
Насправді є інтерфейсом,
або виконання процедури створення
об'єкта переривається з яких-небудь іншим
причин.
IllegalAccessException - якщо клас або його
конструктор без аргументів недоступні.

15.

SecurityException - якщо діюча політика
безпеки забороняє створення нових об'єктів
ExceptionInInitializerError -вибрасивается при
ініціалізації класу.
У класі Constructor визначені і інші методи.
public Сlass getParameterTypes ()

відповідних типів параметрів, які
задані в оголошенні поточного конструктора.
public Class getExceptionTypes ()
Повертає масив об'єктів Class,
відповідних типів винятків, які
задані в реченні throws оголошення
поточного конструктора.

16.

public Object newlnstance (Object args)
throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
Використовує конструктор, що представляється поточним
об'єктом Constructor, для створення і ініціалізації
нового екземпляра класу, в якому конструктор
оголошений, з передачею заданих аргументів.
Повертає посилання на новостворений і
ініціалізований об'єкт. Довжина масиву args
повинна збігатися з числом параметрів в
оголошенні конструктора, а типи об'ектовелементов масиву повинні допускати присвоювання
відповідним типам параметрів конструктора -
в іншому випадку буде викинуто виключення
IllegalArgumentException.

17.

Розглянемо приклад:
class Myclass (
private int a;
public Myclass (int k) (a = k;)
public int func (int a, int b) (return a + b;)
}
public class Main (
public static void main (String args) (
try (
String name = "Myclass";
Class mycl = Class.forName (name);
Class d = (int.class);
Constructor c = mycl.getConstructor (d);
Myclass ob = (Myclass) c.newInstance (new Object (
new Integer (10)));
System.out.println (ob.func (3,5)); )
catch (Exception e) ();
}}

18.

клас AccessibleObject
Класи Field, Constructor і Method є
похідними від класу AccessibleObject,
який дає можливість вирішувати або
забороняти перевірку ознак доступу рівня
мови, таких як public і private.
Клас AccessibleObject має методи
1. public void setAccessible (boolean flag)
Встановлює прапор доступу до об'єкта в
відповідно до значення аргументу: true
означає, що об'єкт більше не підкоряється
правилами доступу, що встановлюються на рівні
мови (і буде завжди доступний), a false
змушує об'єкт підтримувати заданий
рівень доступу.
Якщо повноважень зі зміни прапора доступу
недостатньо, викидається виключення типу
SecurityException

19.

2. public static
void setAccessible (AccessibleObject array,
boolean flag)
Дозволяє встановити прапор доступу до
об'єктам, переданим у вигляді масиву.
Якщо в процесі обробки чергового
об'єкта викидається виключення типу
SecurityException, об'єкти, розташовані
в масиві раніше, зберігають знову задані
значення рівня доступу, а всі інші
об'єкти залишаються в колишньому стані.
3. public boolean isAccessible ()
Повертає поточне значення прапора доступу
до об'єкта

20.

клас Array
Клас Array використовується для створення масиву
засобами рефлексії.
Для створення масивів використовуються дві форми методу
newInstance.
public Object newlnstance (Class compType, int length)
Повертає посилання на новий масив типу compType
заданої довжини length.
public Object newInstance (Class compType, int dim)
Повертає посилання на новий багатовимірний масив типу
compType, розмірності якого задані значеннями
елементів масиву-параметра dim.
Якщо масив dim порожній або володіє довжиною, що перевищує
допустиму кількість розмірностей (зазвичай 255),

llegalArgumentException.

21.

Розглянемо приклади.
Приклад 1. Сформуємо масив типу byte
byte ba = (byte)
Array.newlnstance (byte.class, 13);
це рівнозначно
byte ba = new byte;
Приклад 2.
int dims = (4, 4);
double matrix = (double)
Array.newlnstance (double.class, dims);
це рівнозначно
double matrix = new double;

22.

Клас Array володіє методами get та set.
Нехай заданий масив ха значень типу int; тоді
висловом xa [i] буде відповідати:
Integer n = Array.get (xa, i)
Присвоїти значення елементу масиву можна так:
xa [i] = 23; - це те ж саме, що
Array.set (xa, i, new Integer (23));
клас Package
Виклик методу getPackage класу Class дозволяє
отримати об'єкт класу Package, що містить
опис пакета, в складі якого визначено
клас (сам клас Package розміщений в пакеті
java.lang).
Метод getName () об'єкта Package повертає
повне ім'я поточного пакета.

23.

клас Proxy
Клас Proxy дозволяє динамічно створювати
класи, що реалізують один або кілька
інтерфейсів.
Припустимо, що є клас A,
який реалізує деякі інтерфейси.
Java-машина під час виконання може
згенерувати проксі-клас для даного
класу A, тобто такий клас, який
реалізує всі інтерфейси класу A, але
замінює виклик всіх методів цих
інтерфейсів на виклик методу invoke,
інтерфейсу InvocationHandler, для
якого можна визначати свої
реалізації.

24.

Створюється проксі-клас з допомогою виклику методу
Proxy.getProxyClass, який приймає ClassLoader і
масив інтерфейсів (interfaces), а повертає об'єкт
класу java.lang.Class, який завантажений за допомогою
переданого ClassLoader і реалізує переданий масив
інтерфейсів.
На передаються параметри є ряд обмежень:
1. Всі об'єкти в масиві interfaces повинні бути
інтерфейсами. Вони не можуть бути класами або
примітивами.
2. У масиві interfaces не може бути двох однакових
об'єктів.
3. Всі інтерфейси в масиві interfaces повинні бути
завантажені тим ClassLoader, який передається в метод
getProxyClass.
4. Все не публічні інтерфейси повинні бути визначені
в одному і тому ж пакеті, інакше генерується проксі-клас
не зможе їх все реалізувати.

25.

5. Ні в яких двох інтерфейсах не може бути
методу з однаковою назвою та
сигнатурою параметрів, але з різними
типами, що повертається.
6. Довжина масиву interfaces обмежена
65535-ю інтерфейсами. Ніякої Java-клас
не може реалізовувати більш 65535
інтерфейсів.

26.

Властивості динамічного проксі-класу
1. Проксі-клас є публічним, забезпечений
модифікатором final і не є абстрактним.
2. Ім'я проксі-класу по-замовчуванням не
визначено, однак починається на Proxy. всі
простір імен, що починаються на Proxy
зарезервовано для проксі-класів
(В останніх версіях Java це не обов'язково).
3. Проксі-клас успадковується від
java.lang.reflect.Proxy.
4. Проксі-клас реалізує всі інтерфейси,
передані при створенні, в порядку передачі.

27.

5. Якщо проксі-клас реалізує непублічний
інтерфейс, то він буде згенеровано в тому пакеті,
в якому визначено цей самий непублічна
інтерфейс. У загальному випадку пакет, в якому
згенерує проксі-клас невизначений.
6. Метод Proxy.isProxyClass повертає true для
класів, створених за допомогою
Proxy.getProxyClass і для класів об'єктів,
створених за допомогою Proxy.newProxyInstance і
false в іншому випадку.
Даний метод використовується підсистемою
безпеки Java і потрібно розуміти, що для
класу, просто успадкованого від
java.lang.reflect.Proxy він поверне false.

28.

Властивості створеного екземпляра проксі-класу наступні:
1. Об'єкт проксі-класу наводимо до всіх інтерфейсів,
переданим в масиві interfaces. Якщо IDemo - один з
переданих інтерфейсів, то операція proxy instanceof
IDemo завжди поверне true, а операція (IDemo) proxy
завершиться коректно.
2. Статичний метод Proxy.getInvocationHandler
повертає обробник викликів, переданий при створенні
примірника проксі-класу. Якщо переданий в даний
метод об'єкт не є екземпляром проксі-класу, то
буде викинуто IllegalArgumentException виняток.
3. Клас-обробник викликів реалізує інтерфейс
InvocationHandler, в якому визначено метод invoke,
має наступну сигнатуру:
public Object invoke (Object proxy, Method method,
Object args) throws Throwable

29.

Розглянемо приклад:
package javaapplication3;
interface Account (
double getBalance ();
void changeBalance (int sum);
void percents (double per);)
class MyAccount implements Account (
private double balance;
public MyAccount () (balance = 0,0;)
public double getBalance () (return balance;)
public void changeBalance (int sum) (
balance + = sum;)
public void percents (double per) (
balance + = balance * per / 100; ); )

30.

class MyAccountProxy implements
InvocationHandler (
private Account ac;
public MyAccountProxy (Account acc) (ac = acc;)
public static Account newInstance (Account da) (
return (Account) Proxy.newProxyInstance (
da.getClass (). getClassLoader (),
da.getClass (). getInterfaces (),
new MyAccountProxy (da));
}

31.

public Object invoke (Object proxy,
Method method, Object args)
throws Throwable (
if (method.getName () == "percents") (
double d = ((Double) args) .doubleValue ();
if (d<0) d=0;
if (d> 30) d = 30;
args = new Double (d);

else (
return method.invoke (ac, args); )
}
}

32.

public class Main (
public static void main (String args) (
MyAccount ma = new MyAccount ();
Account
a = (Account) MyAccountProxy.newInstance (ma);
a.changeBalance (150);

a.percents (20);
System.out.println (a.getBalance ());
a.percents (35);
System.out.println (a.getBalance ());))

33.

Завантаження класів
Виконуюча система завантажує класи в міру
виникнення необхідності в них.
Функціональні особливості процедур завантаження
класів істотно залежать від
реалізації віртуальних машин Java, але в
більшості випадків для відшукання класів,
адресованих додатком, але не завантажених
виконуючою системою, застосовується механізм
перегляду шляху пошуку класів.
Щоб створити додаток, яке в змозі
завантажувати класи способами, відмінними від
передбачених за замовчуванням, слід
скористатися об'єктом класу ClassLoader,
здатним отримати байт-код реалізації потрібного
класу і завантажити його в середу виконуючої
системи.

34.

Клас ClassLoader є абстрактним класом.
Для створення власного завантажувача класів,
необхідно створити клас - спадкоємець від
ClassLoader і перевизначити метод
protected Class findClass (String name) throws
ClassNotFoundException
Який знаходить байт-код класу з заданим
ім'ям name і завантажує дані в середу
віртуальної машини, повертаючи об'єкт Class,
представляє знайдений клас.
Об'єкт-завантажувач здатний делегувати
повноваження щодо завантаження класів "батьківському"
завантажувачу класів (parent class loader).
"Батьківський" завантажувач класів може бути
заданий як аргумент конструктора класу
ClassLoader.

35.

protected ClassLoader ()
Створює об'єкт ClassLoader, неявно
використовуючи в якості "батьківського"
завантажувача класів системний завантажувач
(Який може бути отриманий за допомогою
виклику методу getSystemClassLoader).
protected ClassLoader (ClassLoader parent)
Створює об'єкт ClassLoader, використовуючи
заданий "батьківський" завантажувач класів.
Основним в складі класу ClassLoader
є метод loadClass

36.

public Сlass loadClass (String name) throws
ClassNotFoundException
повертає об'єкт Class для класу з заданим
ім'ям і при необхідності завантажує цей
клас. Якщо клас не може бути завантажений,
викидається виключення типу
ClassNotFoundException.
Схема завантаження класів, пропонована методом
loadClass за замовчуванням і зазвичай не
переобумовленої, виглядає так:
1. перевірити за допомогою виклику методу
findLoadedClass класу ClassLoader, що не
завантажувався заданий клас раніше; в складі
ClassLoader передбачена таблиця об'єктів
Class для всіх класів, завантажених засобами
поточного завантажувача класів; якщо клас був
завантажений перш, метод findLoadedClass
поверне посилання на існуючий об'єкт Class;

37.

2. якщо клас не завантажується, викликається
loadClass "батьківського" завантажувача
класів; якщо поточний завантажувач НЕ
володіє "батьком", використовується
системний завантажувач класів;
3. якщо клас все ще не завантажений,
викликається метод findClass, що виконує
пошук і завантаження класу.
Таким чином, необхідно реалізувати
власні версії наступних методів
ClassLoader:

38.

protected synchronized Class
loadClass (String name, boolean resolve)

protected Class findClass (String name)
throws ClassNotFoundException
protected java.net.URL findResource (String name)
protected java.util.Enumeration
findResources (String name) throws IOException
(Абстрактний клас ClassLoader представляє
тільки реалізацію методу loadClass, засновану
на protected-методах - findLoadedClass і findClass).

39.

Розглянемо приклад.
class PlayerLoader extends ClassLoader (
public Class findClass (String name) throws
ClassNotFoundException (
try (
byte buf = bytesForClass (name);
return defineClass (name, buf, 0, buf.length);
}
catch (IOException e) (
throw new ClassNotFoundException (e.toString ());
}
}
// ... Оголошення методу bytesForClass та інших
методів
}

40.

Метод findClass зазвичай виконує дві
функції.
По-перше, він повинен виявити байт-код
заданого класу і зберегти його в масиві
типу byte - цей обов'язок в прикладі
покладено на метод bytesForСlass.
По-друге, він використовує прикладний метод
defineСlass, щоб виконати фактичну
завантаження класу, що визначається байт-кодом.
Метод defineСlass має вигляд

41.

protected final Class defineClass (String name,
byte data, int offset, int length) throws
ClassFormatError
Повертає об'єкт Class для класу з заданим ім'ям
name; бінарне представлення класу передається в
вигляді масиву data.
Для завантаження класу використовуються тільки байти,
містяться в елементах масиву data з індексами
від offset до offset + length. Якщо байти із зазначеного
проміжку не задовольняють необхідному формату
опису класу, викидається об'єкт виключення
типу ClassFormatError.
Метод відповідальний за збереження посилання на об'єкт
Class для завантаженого класу в таблиці завантажених
класів, що переглядається методом findLoadedClass.

42.

Розглянемо метод bytesForClass.
protected byte bytesForClass (String name) throws
lOException, ClassNotFoundException (
FileInputStream in = null;
try (


if (length == 0) throw new ClassNotFoundException (name);
byte buf = new byte;

return buf;
}
finally (
if (in! = null) in.close ();
}
}

43.

Таким чином повний код має вигляд:
import java.lang.reflect. *;
import java.io. *;
class MyClassLoader extends ClassLoader (
public ClassfindClass (String name) throws
ClassNotFoundException (
byte buf = ReadFromBuffer (name);
if (name.equals ( "MyInterface1")) (

) Else if (buf == null) (
return findSystemClass (name);
) Else (
return defineClass (name, buf, 0, buf.length);
}
}

44.

protected byte ReadFromBuffer (String name) throws
ClassNotFoundException (
FileInputStream in = null;
try (
in = new FileInputStream (name + ".class");
int length = in.available (); // число доступних байтів
if (length == 0) throw
new ClassNotFoundException (name);
byte buf = new byte;
in.read (buf); // Зчитування байтів
return buf;
}
catch (FileNotFoundException e) (return null;)
catch (IOException e) (return null;)
finally (
try (if (in! = null) in.close ();)
catch (IOException e) ()
}
}

45.

protected synchronized Class
loadClass (String name, boolean resolve) throws
ClassNotFoundException (
Class result = findClass (name);
if (resolve) resolveClass (result);
return result;
}
}

46.

public class Main1 (
public static void main (String args) (
try (
String name = "Myclass";
ClassLoader ld = new MyClassLoader ();
Class cl = Class.forName (name, true, ld);
Constructor s = cl.getConstructor (int.class);
MyInterface1
ob = (MyInterface1) s.newInstance (
new Integer (8));
System.out.println (ob.func (3,5));
) Catch (Exception e) ();
}
}

47.

public interface MyInterface1 (
public int func (int a, int b);
}
public class Myclass implements MyInterface1 (
private int a;
public Myclass (int k) (a = k;)
public int func (int a, int b) (return a + b;)