Java модифікатори. Модифікатори в Java: static, final, abstract, synchronized, transient, volatile. Модифікатори static, abstract та final

Останнє оновлення: 03.10.2019

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

У C# застосовуються такі модифікатори доступу:

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

    private: закритий клас або член класу. Представляє повну протилежність модифікатору public. Такий закритий клас чи член класу доступний лише з коду у тому класі чи контексті.

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

    internal : клас і члени класу з подібним модифікатором доступні з будь-якого місця коду в тій самій збірці, проте він недоступний для інших програм та збірок (як у випадку з модифікатором public).

    protected internal : поєднує функціонал двох модифікаторів. Класи та члени класу з таким модифікатором доступні з поточної збірки та похідних класів.

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

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

Private protected class State ( internal int a; protected void Print() ( Console.WriteLine($"a = (a)"); ) )

Або можемо не вказувати:

Class State ( int a; void Print() ( Console.WriteLine($"a = (a)"); ) )

Якщо для полів і методів не визначено модифікатор доступу, то для них застосовується модифікатор private .

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

Усі класи та структури, визначені безпосередньо у просторах імен і які є вкладеними інші класи, можуть лише модифікатори public чи internal.

Подивимося на прикладі та створимо наступний клас State:

Public class State ( // все одно, що private int defaultVar; int defaultVar; // поле доступне тільки з поточного класу private int privateVar; // доступно з поточного класу та похідних класів, які визначені в цьому ж проекті protected private int protectedPrivateVar; // Доступно з поточного класу і похідних класів protected int protectedVar; // доступно в будь-якому місці поточного проекту internal int internalVar; будь-якому місці програми, а також для інших програм та збірок public int publicVar; // за замовчуванням має модифікатор private void defaultMethod() => Console.WriteLine($"defaultVar = (defaultVar)") private void privateMethod() => Console.WriteLine($"privateVar = (privateVar)"); // доступний з поточного класу та похідних класів, які визначені в цьому ж проекті protected private void protectedPrivateMethod() => Console.WriteLine($ "protectedPrivateVar = (protectedPrivateVar)");

// доступний з поточного класу та похідних класів protected void protectedMethod()=> Console.WriteLine($"protectedVar = (protectedVar)");

// доступний будь-де поточного проекту internal void internalMethod() => Console.WriteLine($"internalVar = (internalVar)");

Тепер подивимося, як ми зможемо використовувати змінні нашого класу в програмі (тобто в методі Main класу Program), якщо класи State та Program знаходяться в одному проекті:

Class Program ( static void Main(string args) ( State state1 = new State(); // присвоїти значення змінної defaultVar у нас не вийде, // оскільки вона має модифікатор private і клас Program її не бачить // І цей рядок середа підкреслить як неправильну state1.defaultVar = 5; //Помилка, отримати доступ не можна // те саме стосується і змінної privateVar state1.privateVar = 5; // Помилка, отримати доступ не можна // присвоїти значення змінної protectedPrivateVar не вийде, // оскільки клас Program не є класом-спадкоємцем класу State state1.protectedPrivateVar =5; // Помилка, отримати доступ не можна // присвоїти значення змінної protectedVar теж не вийде, // оскільки клас Program не є класом-спадкоємцем класу State state1.protectedVar = 5; // Помилка, отримати доступ не можна // Змінна internalVar з модифікатором internal доступна з будь-якого місця поточного проекту // тому спокійно надає їй значення state1.internalVar = 5;

// змінна protectedInternalVar також доступна з будь-якого місця поточного проекту state1.protectedInternalVar = 5;

// Змінна publicVar загальнодоступна state1.publicVar = 5;

)

Таким чином, ми змогли встановити тільки змінні міжнародніVar, ProtectedInternalVar і publicVar, так як їх модифікатори дозволяють використовувати в даному контексті.

Аналогічно і з методами:

Незважаючи на те, що модифікатори public і internal схожі на свою дію, але вони мають велику відмінність. Класи та члени класу з модифікатором public також будуть доступні й іншим програмам, якщо дані класу помістити в динамічну бібліотеку dll і потім її використовувати в цих програмах.

Мова 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, можна використовувати символи контролю доступу для захисту доступу до класів, змінних, методів і конструкторів. Java підтримує чотири різні права доступу.

За замовчуванням також відомий як значення по замовчуванням,видимий у тому самому пакеті, не використовують які-небудь модифікатор.

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

Є, щоб вказати загальниймодифікатор, видимий всім класів.

Захищений, захищенийМодифікатор визначає, що для всіх класів і підкласів в межах того ж видимого пакета.

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

Використовуйте змінні та методи, оголошені модифікатором доступу за умовчанням для класу в межах того ж пакета видно. Інтерфейс де змінні неявно оголошений як публічним статичним фіналом, так і інтерфейс, де метод доступу за замовчуванням для публіки.

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

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

Приватний доступ модифікатор -private

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

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

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

Наступні класи використовують приватний модифікатор доступу:

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

Наприклад, змінний формат класу Logger є приватною змінною, тому інші класи не можуть безпосередньо отримати і встановити значення змінної. Для того, щоб мати можливість працювати з іншою змінною класу визначає два відкритих методи: GetFormat () (формат значення, що повертається) і SetFormat (String) (налаштування формату)

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

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

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

Наступні функції використовують контроль доступу громадськості:

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

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

Захищені модифікатори доступу охороняються

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

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

модифікатор Підкласи можуть отримати доступ оголошено Захищені методи та змінні, так що ми можемо захистити непов'язані класи, використовуючи ці методи та змінні.

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

Class AudioPlayer (protected boolean openSpeaker(Speaker sp) ( // 实现细节)) class StreamingAudioPlayer (boolean openSpeaker(Speaker sp) (//

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

Контроль доступу та успадкування

Зверніть увагу на такі методи успадкували правила:

    Батьківський клас оголошено як публічні методи у підкласі також має бути публічним.

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

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

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

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

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

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

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

Синхронні та леткі модифікатори, в основному для потоків програмування.

Статичний модифікатор

    Статичні змінні:

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

    Статичні методи:

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

Доступ до змінних класу та методи можуть бути використані безпосередньо classname.variablename і classname.methodname доступу.

У наступному прикладі статичний модифікатор використовується для створення методів класу і змінних класів.

Public class InstanceCounter ( private static int numInstances = 0; protected static int getCount() ( return numInstances; ) private static void addInstance() ( numInstances++; ) InstanceCounter() ( InstanceCounter.addInstance(); ) ( System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i< 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }

Приклади наведених вище результатів операції редагування так:

Started with 0 instances Створено 500 instances

Остаточний класифікатор

Кінцеві змінні:

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

Остаточний модифікатор зазвичай використовується разом, щоб створити статичну константу класу модифікатора.

Public class Test( final int value = 10; // 下面是声明常量的实例 public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //将输出一个错误 } } !}

Остаточний метод

Методи кінцевого класу успадковуються підкласами, але не можуть змінювати підкласи.

Основна мета методу полягає в тому, щоб запобігти остаточній заяві цього методу змінюється.

Як показано нижче, з використанням кінцевих методів модифікаторів декларації.

Public class Test( public final void changeName()( // 法体 ) )

Остаточна категорія

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

Public final class Test ( // 类体 )

Анотація модифікатор

Абстрактний клас:

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

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

Абстрактний клас може містити абстрактні методи та не абстрактні методи.

Abstract class Caravan( private double price; private String model; private String year; public abstract void goFast(); // 추상 public abstract void changeColor(); )

Абстрактний метод

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

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

Якщо клас містить ряд абстрактних методів, клас має бути оголошений як абстрактний клас. Анотація клас не може містити абстрактні методи.

Абстрактне оголошення методу закінчується крапкою з комою, наприклад: громадський абстрактний зразок ();

Public abstract class SuperClass( abstract void m(); / / abstract method ) class SubClass extends SuperClass ( // 实现 abstract void m()

Синхронний модифікатор

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

Public synchronized void showDetails()( ....... )

Перехідний модифікатор

Серіалізована об'єкт містить модифіковані перехідними змінними екземпляра віртуальної машини Java (JVM), щоб пропустити цю конкретну змінну.

Модифікатор включений у визначення змінних заяв для попередньої обробки класів типів даних і змінних.

Public transient int limit = 55; // will not persist public int b; // will persist

Летючі Модифікатори

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

Public class MyRunnable implements Runnable (priv. volatile boolean active; )

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

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

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

Модифікатори в 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 говоритимемо у статті ОВП.

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

5

Я бачив деякі дискусії у StackOverflow про цю тему, але я не бачу щось, що допомогло мені зрозуміти наступний пункт:

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

C++ також має класи «друг», які можуть мати доступ до приватних/захищених камер класу, які дають «дружбу». Це трохи схоже на модифікатор поля «package» в Java (модифікатор поля за замовчуванням), за винятком того, що в C++ дружба дає доступ до всіх закритих членів, але Java доступ з класів в одному пакеті специфічний для поля класу,

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

Але на Java я не знаю, як це зробити, оскільки за допомогою «захищеного» модифікатора поля – я також надаю доступ до всіх класів у пакеті. Єдиний спосіб, яким я знаходжу це, – оголосити захищене поле та ізолювати клас у своєму пакеті.

Звідси я укладаю, що угруповання класів в один пакет має виконуватися з урахуванням «дружби» між класами. Чи це є провідним фактором при групуванні пакетів?

Ще одна річ, яку я не розумію, в Java, припускаючи, що я маю два поля в класі A: b, c. Я хочу дати доступ B, але не до, і я хочу дати доступ C, але не b. і до "Світу" я хочу b, c, щоб приховати. Як це можна зробити? Я припускаю, що B, C повинні бути в тому ж пакеті, що і A. але шляхом оголошення b, c з пакетоммодифікатором Я дозволяю B, C доступ як до, так і до. Чи є спосіб Java, щоб це зробити?

Надія на деяке пояснення цього питання

11

Найкраще питання, якщо менш корисним для вас буде вужчим і конкретнішим. Загальне питання «все про конфіденційність у Java та C++ і про те, як вони відрізняються», більш ніж занадто широке. Чи можете ви поставити більш конкретне питання про конкретнішу проблему? - Yakk 04 берез. 15 2015-03-04 16:38:58

  • 4 відповіді
  • Сортування:

    Активність

2

У C++, коли використовується захист, тільки підклас може отримати доступ до елемента (аналог поля Java).

Специфікатори доступу також призначені для функцій-членів/методів, а не лише для змінних-членів.

У C++ є також «друг» класи, які можуть мати доступ до приватних/захищених mambers класу, що дає «дружбу». Цей трохи схожий на модифікатор поля "package" в Java (за замовчуванням модифікатор поля), за винятком того, що в C++ дружба дає доступ до всіх приватних членів, але Java доступ з класів в тому ж пакеті специфічний для поля класу.

Існує не тільки friend класи, але й функції.

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

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

Але в Java, я не знаю, як я можу це зробити,

Відповідь: Ви не можете.

оскільки за допомогою «захищеного» модифікатора поля – я також надаю доступ до всіх класів у пакеті.

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

Технічно, так. Але це творить інші проблеми. Ваш клас не зможе отримати доступ до приватних частин пакета свого попереднього пакета. Допустимо, ваш BaseClass був у com.example.one . Ви перемістите його на com.example.two. Тепер він більше не зможе отримати доступ до інших пакетів-приватних класів com.example.one.

Чи це є провідним фактором при групуванні пакетів?

Так, Java спроектовано таким чином. Ви можете спробувати боротися з правилами мовиале це програшна битва будь-якою мовою програмування.

Ще одна річ, яку я не розумію, в Java, припускаючи, що я маю два поля в класі A: b, c. Я хочу дати B доступ до b, але не, і я хочу надати C доступ до c, але не b. і в "Світ" я хочу b, c, щоб приховати. Як це можна зробити?

Це не може бути зроблено чистим способом (чистим я маю на увазі: без будь-яких зломів, які вимагатимуть від вас перевірки стеку викликів під час виконання та виключення винятків).

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

1

Це досить купа питань разом...

Але в Java, я не знаю, як я можу це зробити, тому що в силу використовуючи «захищений» модифікатор поля – я також надаю доступ до всіх класів у пакеті.

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

Єдиний спосіб, яким я знаходжу це, – оголосити захищене поле та ізолювати його у своєму пакеті.

Це технічно правильно, хоча це мало використовувати. Упаковка класів призначена для угруповання пов'язаних класів, де «родинні» означає «класи, які виконують конкретне ставлення», тобто. сутності і т.д.

Звідси я укладаю, що угруповання класів в один пакет має виконуватися з урахуванням «дружби» між класами. Чи це є провідним фактором при групуванні пакетів?

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

Для ваших класів A, B і C, наприклад, з атрибутами:

Я думаю, B, C має бути як у тому ж пакеті, А. а оголошує б, з модифікатором упаковки I нехай В, C доступ як до b, так і до. Чи є спосіб Java зробити це?

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

0

Коротка відповідь: немає жодного способу зробити це.

Якщо ви турбуєтеся про вторгнення від клієнтів ін'єкційного класу в пакеті, щоб отримати несанкціонований доступ, ви можете переміщати чутливий код в окремому пакеті, і зробити пакет запечатаного в банку ви доставити його: http://docs.oracle.com/javase/tutorial /deployment/jar/sealman.html

1

Неявно передбачається, що всі класи в пакеті «знають» один одного (бо вони були написані однією і тією ж особою/компанією/організацією). Таким чином, вони або не отримують доступу до полів protected , або якщо вони це роблять, вони знають, як це зробити належним чином.

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

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

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

Звичайно, ви можете придумати складний протокол обміну токенами, щоб зробити це поле доступним тільки для екземплярів B/C, але це було б чудовою накладною витратою, а інший об'єкт все одно може використовувати відображення, щоб отримати доступ до всіх приватних членів, якщо ви не відключіть його за допомогою політик безпеки, що зазвичай не так, але знову ж таки, політики безпеки в кінцевому підсумку вирішуються власником JVM.

Отже, в кінцевому підсумку кращий спосіб зробити те, що ви говорите на Java, - або помістити їх в той самий пакет, або написати B і C як внутрішні класи A, щоб вони могли безпосередньо звертатися до закритих членів A і їх піддавати їх похідним класам.

Public class A ( public static abstract class B ( protected Whatever getWhatever(A a) ( return a.b; ) protected void setWhatever(A a, Whatever value) ( ​​a.b = value; ) ) public static abstract class C ( protected Whatever getWhate a) ( return a.c; ) protected void setWhatever(A a, Whatever value) ( ​​a.c = value; ) ) private Whatever b;

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

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

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

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

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

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

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

За умовчанням класи верхнього рівня доступні в пакеті, в якому вони визначені. Втім, якщо клас верхнього рівня оголошено як 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. Далі наведу просто скріни цих класів та результат роботи програми: