Яка різниця між загальнодоступними, захищеними, пакетно-приватними та приватними на Java?


3171

В Java, є чіткі правила про те, коли використовувати кожен з модифікаторів доступу, а саме : за замовчуванням (приватний пакет), public, protectedі private, роблячи classі interfaceраз зі спадкуванням?


161
privateховається від інших класів в межах пакету. publicпіддається заняттям поза пакетом. protected- версія, publicобмежена лише підкласами.
Помітно

87
@Tennenrishin - Ні; на відміну від C ++, у Java protectedробить метод також доступним з усього пакету. Ця дурість у моделі наочності Яви порушує мету protected.
Ніколя Барбулеско

35
@Nicolas Це доступно з усієї упаковки, з або без protected. Як модифікатор доступу , все, що protectedпотрібно зробити, це піддавати підкласам поза пакетом.
Помітно

15
@tennenrishin - ну ось що сказав Ніколяс ... і ти це просто повторюєш зараз. Ви спочатку говорили, що це protected- і я цитую - "це версія публічного обмеження лише на підкласи", що не відповідає дійсності, оскільки захищений також дозволяє отримати доступ через весь пакет (ерго, це не обмежує доступ до підкласів. )
luis.espinal

10
Я також погоджуюся з Ніколасом у тому, що захищений режим доступу на Яві є ідіотичним. Що сталося, це те, що Java поєднував горизонтальні (гратчасті) та вертикальні обмеження доступу. Область застосування за замовчуванням - це горизонтальне / решіткове обмеження, решітка є пакетом. Паблік - це ще одне горизонтальне обмеження, де ґрати - це весь світ. Приватні та (C ++) захищені вертикально. Було б краще, якби у нас був перекреслений доступ, скажімо, protected-packageдля тих рідкісних випадків, коли він насправді потребував цього, залишаючи protectedеквівалентну захищеній версії C ++.
luis.espinal

Відповіді:


5636

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

______________________________________________________________
| │ Клас │ Пакет │ Підклас │ Підклас │ Світ |
| │ │ │ (той же pkg) │ (розл. Pkg) │ |
| ───────────────────────────────────────────────────── ──┼──────── |
| громадські │ + │ + │ + │ + │ + | 
| ───────────────────────────────────────────────────── ──┼──────── |
| захищені │ + │ + │ + │ + │ | 
| ───────────────────────────────────────────────────── ──┼──────── |
| немає модифікатора│ + │ + │ + │ │ | 
| ───────────────────────────────────────────────────── ──┼──────── |
| приватні │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +: доступний бланк: недоступний

5
Таблиця, наведена вище, неправильна, оскільки навіть ті самі privateчлени можуть бачити / використовувати будь-який клас / статичний метод у тому самому вихідному файлі.
Усагі Міямото

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

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

3
Наприклад, якщо у мене є MyClassі я роблю, AnotherClass extends MyClassя матиму доступ до всіх захищених та публічних методів та властивостей зсередини AnotherClass. Якщо я MyClass myClass = new MyClass();в AnotherClassде - небудь - скажімо , конструктор - я буду мати доступ тільки до публічних методам , якщо він знаходиться в іншому пакеті. Зауважте, що якщо я = new MyClass() { @Override protected void protectedMethod() { //some logic } };це зробити, то, мабуть, я можу отримати доступ до захищених методів, але такий самий, як розширення, але натомість вбудований.
adprocas

3
На жаль, ця відповідь є грубим спрощенням. Реальність дещо складніша, особливо якщо врахувати protected(що насправді є досить складним модифікатором доступу, який можна зрозуміти повністю - більшість людей, які думають, що знають, що protectedозначає насправді, немає). Крім того, як зауважив Богем, це не відповідає на питання - воно нічого не говорить про те, коли використовувати кожен модифікатор доступу. На мою думку, ця відповідь не є достатньо поганою, аби підкреслити, але близьку. Але понад 4000 грошей? Як це сталося?
Давуд ібн Карім

483

(Caveat: Я не Java-програміст, я програміст Perl. Perl не має офіційних захистів, тому, можливо, я так добре розумію проблему :))

Приватний

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

Пакет приватний

Його можна побачити і використовувати лише той пакет, в якому він був задекларований. Це за замовчуванням у Java (що деякі вважають помилкою).

Захищений

Пакет "Приватний +" можна побачити підкласи або учасників пакету.

Публічний

Кожен може це побачити.

Опубліковано

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

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

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

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

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

Особисто я дотримуюся лише "приватного" та "публічного". Багато мов OO просто мають це. "Захищений" може бути корисним, але це дійсно обман. Коли інтерфейс стає більш ніж приватним, він знаходиться поза вашим контролем, і вам потрібно буде шукати код інших людей, щоб знайти використання.

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

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


26
друзі -> "Чим менше ви знаєте про це, тим краще" ---> Це дає вибіркову видимість, яка все ще перевершує конфіденційність пакету. У C ++ він має своє використання, оскільки не всі функції можуть бути членами, а друзі - це краще, ніж публікація. Звичайно, існує небезпека неправильного використання злими розумами.
Себастьян Мах

30
Слід також зазначити, що "захищений" у C ++ має інше значення - захищений метод є фактично приватним, але все ж його можна викликати з класу успадкування. (На відміну від Java, де його можна викликати будь-яким класом у межах одного пакету.)
Rhys van der Waerden

9
@RhysvanderWaerden C # є таким самим, як C ++ у цьому аспекті. Мені здається дивним, що Java не дозволяє оголосити члена, доступного для підкласу, але не для всього пакету. Мені це щось перевернуто - пакет має ширший обсяг, ніж дитячий клас!
Конрад Моравський

15
Пакет IMKO @KonradMorawski має менший обсяг, ніж підклас. Якщо ви ще не оголосили свій клас остаточним, користувачі повинні мати можливість його підкласифікувати - тому захищена Java є частиною опублікованого інтерфейсу. OTOH, пакунки неявно розробляються однією організацією: наприклад, com.mycompany.mypackage. Якщо ваш код заявляє про себе в моєму пакеті, ви неявно оголошуєте себе частиною моєї організації, тому ми повинні спілкуватися. Таким чином, пакунок публікується для меншої / легшої для охоплення аудиторії (людей у ​​моїй компанії), ніж підклас (люди, які розширюють мій об’єкт), і так вважається меншою видимістю.
однойменний

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

434

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

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

Пояснення

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

  • Член без модифікатора доступу ( j) доступний лише у класах одного пакету.

  • Захищений член ( k) доступний у всіх класах в одному пакеті і в підкласах в інших пакетах.

  • Громадський елемент ( l) доступний для всіх класів (якщо він не знаходиться в модулі , який не експортувати пакет, який оголошений в).


Який модифікатор вибрати?

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

Приклади:

  • Поле, long internalCounterймовірно, має бути приватним, оскільки воно є змінним та детальним про реалізацію.
  • Клас, який повинен бути екземпляром лише у заводському класі (у тому ж пакеті), повинен мати конструктор з обмеженим пакетом, оскільки він не повинен мати можливість викликати його безпосередньо поза пакетом.
  • Внутрішній void beforeRender()метод, викликаний безпосередньо перед рендерінгом і використовуваний як гачок у підкласах, повинен бути захищений.
  • void saveGame(File dst)Метод , який викликається з коду GUI повинен бути публічним.

(*) Що таке інкапсуляція?


11
Просто кажу: є багато людей, які мають проблеми з розрізненням червоного / зеленого забарвлення. Таблиці, що використовують схеми фарбування червоного / зеленого (або жовтого / оранжевого / ...), рідко "краще" ні для чого ;-)
GhostCat

1
@GhostCat, я не згоден. Я думаю , що червоний / зелений Вирівнює інтуїтивно з «роботою» / «не працює» для багатьох людей, тобто це краще , ніж у багатьох альтернатив.
aioobe

8
colourblindawareness.org/colour-blindness/… ... 8% кольорових сліпих чоловіків можна розділити приблизно на 1% дейтеранопи, 1% протанопів, 1% протаномалів та 5% двосторонніх . І оскільки я одна з тих 50% з цих 5%, будьте впевнені: червоний / зелений смокче.
GhostCat

6
@GhostCat Добре. Це більша частина населення, ніж я очікував. Я завантажив зображення в цей симулятор сліпості кольорів і протестував всі різні режими. Навіть в режимі монохромності / ахроматопсії різниця кольорів є розумною. Ви можете бачити різницю або тренажер вимкнений? (Я все ще вважаю, що червоний / зелений дуже інтуїтивно зрозумілий для людей, що бачать кольори.)
aioobe

3
Я бачу різницю, але я також здатний пройти половину тестів на дальтонізм, які ми повинні зробити в Німеччині для отримання водійських прав ;-) ... але я думаю, що такий симулятор "досить хороший".
GhostCat

206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________

1
Варто сказати словами - "Захищений модифікатор робить об'єкт доступним для інших пакетів, тоді як модифікатор за замовчуванням / без модифікатора обмежує доступ до того ж пакету"
vanguard69

2
@ vanguard69, protectedмодифікатор робить помічену річ (клас, метод чи поле) доступною для якогось іншого класу в якомусь іншому пакеті, лише якщо iff сказав, що інший клас є підкласом класу, де оголошена ця protectedпозначена річ .
Абдулл

"непідданий"? "цей підклас в іншому пакеті"? Ага. Я думав, що знаю Яву.
sehe

@AlexanderFarber Ви оптимізували для конкретної конфігурації браузера? Це зараз мій хром, і це Firefox
1717

Хм, давайте повернемо мої зміни тоді
Олександр Фарбер

165

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

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

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

Крім того, використовуйте примітку @Override при переосмисленні, щоб уникнути зламування рефактора.


3
@RuchirBaronia, "world" = весь код у додатку, незалежно від того, де він знаходиться.
Андрейс

116

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

Доступ "за замовчуванням" (визначений відсутністю ключового слова) також називається пакетно-приватним . Виняток: в інтерфейсі жоден модифікатор не означає загальнодоступний доступ; інші модифікатори, окрім загальнодоступних, заборонені. Константи Енума завжди публічні.

Підсумок

Чи дозволений доступ до члена із цим специфікатором доступу?

  • Учасник private: Тільки якщо член визначений у тому ж класі, що і код виклику.
  • Учасник пакету приватний: Тільки якщо код виклику знаходиться в пакеті, що безпосередньо додається.
  • Учасник protected: той самий пакет, або якщо член визначений у надкласі класу, що містить код виклику.
  • Учасник public: Так.

До яких специфікаторів доступу застосовуються

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

Для класів у верхній області дозволені лише publicта приватні пакети. Такий дизайн, по- видимому , тому protectedі privateбуде зайвим на рівні пакета (немає успадкування пакетів).

Усі специфікатори доступу можливі для членів класу (конструктори, методи та статичні функції членів, вкладені класи).

Супутнє: Доступність класу Java

Замовлення

Специфікатори доступу можуть бути строго упорядковані

громадський> захищений> пакет-приватний> приватний

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

Примітки

  • Методи класу за які дозволили отримати доступ до приватних членам інших об'єктів того ж класу. Точніше, метод класу C може отримати доступ до приватних членів C на об'єктах будь-якого підкласу C. Java не підтримує обмеження доступу за примірниками, лише класом. (Порівняйте зі Scala, яка підтримує її використання private[this].)
  • Для побудови об'єкта вам потрібен доступ до конструктора. Таким чином, якщо всі конструктори приватні, клас може бути побудований лише за кодом, що живе в межах класу (як правило, статичні заводські методи або ініціалізатори статичної змінної). Аналогічно для пакетних або приватних конструкторів.
    • Тільки наявність приватних конструкторів також означає, що клас не можна підкласифікувати зовні, оскільки Java вимагає від конструкторів підкласу неявно або явно викликати конструктор надкласового класу. (Однак він може містити вкладений клас, який його підкласи.)

Внутрішні класи

Ви також повинні враховувати вкладені сфери, наприклад, внутрішні класи. Приклад складності полягає в тому, що внутрішні класи мають членів, які самі можуть приймати модифікатори доступу. Таким чином, ви можете мати приватний внутрішній клас із державним членом; чи можна отримати доступ до члена? (Див. Нижче.) Загальне правило - дивитися на сферу застосування та рекурсивно мислити, чи можна отримати доступ до кожного рівня.

Однак це досить складно, і для отримання детальної інформації зверніться до специфікації мови Java . (Так, помилки компілятора були раніше.)

Для смаку того, як вони взаємодіють, розглянемо цей приклад. Можна «просочити» приватні внутрішні класи; зазвичай це попередження:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Вихід компілятора:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Деякі пов'язані питання:


1
"модифікатори, окрім загальнодоступних, заборонені" - як це стосується Java 9, це вже не так: інтерфейси можуть також мати приватні методи.
MC Імператор

96

Як правило:

  • private: область застосування класу
  • default(або package-private): область упаковки.
  • protected: package scope + child(як пакет, але ми можемо підкласифікувати його з різних пакетів). Захищений модифікатор завжди зберігає відносини «батько-дитина».
  • public: скрізь.

Як результат, якщо ми розділимо право доступу на три права:

  • (D) irect (виклик із методу всередині одного класу або через синтаксис "this").
  • (R) eference (викликати метод, використовуючи посилання на клас або через синтаксис "крапка").
  • (I) наслідування (через підкласифікацію).

тоді у нас є ця проста таблиця:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

54

Вкрай коротко

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

48

Найбільш неправильно зрозумілий модифікатор доступу на Java protected. Ми знаємо, що він схожий на модифікатор за замовчуванням за одним винятком, в якому підкласи можуть бачити його. Але як? Ось приклад, який, сподіваємось, роз’яснює плутанину:

  • Припустимо, що у нас є 2 класи; Fatherі Son, кожен у своєму пакеті:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
  • Додамо захищений метод foo()до Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
  • Метод foo()можна викликати у 4 контекстах:

    1. Всередині класу, який знаходиться в тому ж пакеті, де foo()визначено ( fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
    2. Всередині підкласу в поточному екземплярі через thisабо super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. Посилання, тип якого є одним класом:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
    4. За посиланням, тип якого є батьківський клас, і він знаходиться всередині пакета, де foo()визначено ( fatherpackage) [Це може бути включено всередині контексту №. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • Наступні ситуації не дійсні.

    1. За посиланням, тип якого є батьківський клас, і він знаходиться поза пакетом, де foo()визначено ( fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
    2. Некласклас всередині пакету підкласу (Підклас успадковує захищені члени від свого батьківського складу, і він робить їх приватними для некласових класів):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }

Object#clone()є прикладом protectedчлена.
Eng.Fouad

Яка різниця між вчинками super.foo()та першою недійсною ситуацією f.foo()?
cst1992

1
@ cst1992 Це заплутано, але див. специфікацію мови Java 6.6.2: "Захищений член або конструктор об'єкта може бути доступний поза пакетом, у якому він оголошується лише кодом, який відповідає за реалізацію цього об'єкта". У super.foo () посилання "super" є "безпосередньо відповідальним за реалізацію", але посилання "f" не є. Чому? Тому що ви можете бути на 100% впевнені, що "супер" - це тип батька, але не для "f"; під час виконання це може бути якийсь інший підтип Отця. Дивіться docs.oracle.com/javase/specs/jls/se9/html/…
skomisa

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

30

Приватний

  • Методи, змінні та конструктори

До методів, змінних та конструкторів, які оголошені приватними, можна отримати доступ лише в самому оголошеному класі.

  • Клас та інтерфейс

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

Примітка

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


Захищений

  • Клас та інтерфейс

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

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

Примітка

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


Публічний

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

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

  • Різні пакети

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

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


За замовчуванням - Немає ключового слова:

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

  • У межах тих же Пакетів

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

Примітка

Ми не можемо перевизначити статичні поля. Якщо ви спробуєте її перекрити, вона не показує помилок, але вона не працює, окрім нас.

Відповідні відповіді

Список посилань

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm


21

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


20

Приватний : обмежений доступ лише до класу

За замовчуванням (без модифікатора) : обмежений доступ до класу та пакету

Захищений : обмежений доступ до класу, пакету та підкласів (як всередині, так і зовні)

Загальнодоступне : доступне для класу, пакунків (усіх) та підкласів ... Словом, скрізь.


17

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

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

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

За замовчуванням: Він доступний в одному пакеті з будь-якого класу пакету.

Для доступу ви можете створити об’єкт класу. Але ви не можете отримати доступ до цієї змінної поза пакетом.

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

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

Приватний: це може бути доступ у тому ж класі.

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


16

Доступ до модифікаторів на Java.

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

1. За замовчуванням:

Доступний для класів тільки в одному пакеті.

Наприклад,

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

Цей доступ більш обмежений, ніж публічний та захищений, але менш обмежений, ніж приватний.

2. Громадський

Доступ до нього можна з будь-якого місця. (Глобальний доступ)

Наприклад,

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

Вихід: Привіт

3. Приватний

Доступний лише всередині одного класу.

Якщо ви спробуєте отримати доступ до приватних членів одного класу в іншому, викинете помилку компіляції. Наприклад,

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. Захищений

Доступний лише для класів в одному пакеті та для підкласів

Наприклад,

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

Вихід: Привіт

Введіть тут опис зображення


14
  • загальнодоступний - доступний з будь-якої точки програми.

  • за замовчуванням - доступний з пакета.

  • захищені - доступні з пакету та підкласів іншого пакету. так само

  • приватний - доступний лише для свого класу.


14

Видно в пакеті. За замовчуванням. Модифікатори не потрібні.

Доступний лише для класу ( приватний ).

Видно світові ( публічно ).

Видно в пакеті та всіх підкласах ( захищено ).

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

String name = "john";

public int age(){
    return age;
}

Модифікатор приватного доступу - приватний:

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

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

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

Приклади:

Public class Details{

    private String name;

    public void setName(String n){
        this.name = n;
    }

    public String getName(){
        return this.name;
    }
}

Модифікатор доступу для публічного доступу - загальнодоступний:

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

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

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

Приклад:

public void cal(){

}

Захищений модифікатор доступу - захищено:

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

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

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

12

Ця сторінка добре пише про захищений та модифікатор доступу за замовчуванням

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

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


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

9

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

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


6

Примітка. Це лише доповнення до прийнятої відповіді.

Це пов’язано з модифікаторами доступу Java .

З модифікаторів доступу до Java :

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

  • Елемент списку
  • приватний
  • за замовчуванням (пакет)
  • захищені
  • громадські

З контролю доступу до учасників уроків класу :

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

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

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

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

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

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

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


1
що саме є доповненням, і чому це не редагування існуючої публікації?
вересень

додатком є ​​Модифікатори доступу. Чому б не редагувати? Щоб зберегти прийняту відповідь незмінною для історичних цілей і дати свою відповідь.
ישו אוהב אותך

5

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

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

  1. Клас може бути загальнодоступним або за замовчуванням
  2. Учасники класу можуть бути загальнодоступними, захищеними, за замовчуванням або приватними.

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

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


Defaultне є модифікатором доступу, а два інших - неправильно написані.
користувач207421

5

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

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

  • Коли ви привозите його до кампусу, перше, що ви та ваш друг бачите, це ця статуя. Це означає, що кожен, хто гуляє в кампусі, може подивитися на статую без дозволу університету. Це робить статую ПУБЛІЧНОЮ .

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

  • Ваш друг хоче увійти до WiFi кампусу, але не має жодних даних для цього. Єдиний спосіб, коли він може вийти в Інтернет, це якщо ви поділитесь з ним своїм входом. (Пам’ятайте, кожен студент, який вступає до університету, також має ці дані для входу). Це зробить ваші дані для входу як МОДИФІКЕР .

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

Сподіваюся, це допомагає!


4

Коли ви думаєте про модифікатори доступу, просто подумайте про це таким чином (стосується як змінних, так і методів ):

public-> доступний з кожного місця, де
private-> доступний лише в межах одного класу, де він оголошений

Тепер плутанина виникає, коли мова йде про defaultіprotected

default-> Немає ключового слова модифікатора доступу. Це означає, що вона доступна строго в пакеті класу. Ніде поза цим пакетом не можна отримати доступ.

protected-> Трохи менш суворіші defaultта окрім тих же класів пакетів, до нього можна отримати доступ до підкласів поза пакетом, про який він оголошений.


4

Доступ до Java змінює, які ви можете використовувати

введіть тут опис зображення

Модифікатор доступу може бути застосовний для class, field[О] , method. Спробуйте отримати доступ до цього, підклас або змінити його.

  • Доступ до fieldабо methodє черезclass .
  • Спадщина. classМодифікатором доступу правонаступника (підкласу) може бути будь-який. methodМодифікатор доступу спадкоємця (переопрацювання) повинен бути однаковим або розширити його

Клас верхнього рівня (область першого рівня) може бути publicі default. Nested class[Про] може мати будь-яку з них

package не застосовується до ієрархії пакетів

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


2

Вся справа в інкапсуляції (або, як заявив Джо Філіпс, найменше знань ).

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

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

Наприклад: Ви можете помістити чутливі методи захисту в пакет "безпеки". Потім поставте загальнодоступний клас, який має доступ до деякого коду, пов’язаного із захистом, у цьому пакеті, але зберігайте інші пакети класів безпеки приватними . Таким чином, інші розробники зможуть використовувати загальнодоступний клас за межами цього пакету (якщо вони не змінять модифікатор). Це не функція безпеки, але вона буде керувати використанням.

Outside world -> Package (SecurityEntryClass ---> Package private classes)

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

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


2

приватний захищений-публічний-досконалий-аналогія-для-змінних типів даних

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

введіть тут опис зображення

Примітка. Оголошення членів даних за допомогою приватного специфікатора доступу відоме як приховування даних.

Джерело: Специфікатори доступу - приватні, загальнодоступні та захищені


1
Питання стосувалося Java, а не C ++.
Бенуа

1
@ Benoit Але те, що я розмістив, фотографії в спеціальних, не однакові для обох: java та c ++? Ці правила не застосовуються і для java? дякую
leonidaa

2
У C ++ є лише 3 модифікатори, тоді як у java є 4.
Бенуа

1
аналогія хороша, але специфікатор доступу за замовчуванням відсутній,
mss

1
ОП задало питання "Яка різниця між загальнодоступними, захищеними, пакетно-приватними та приватними в Java?"
JL_SO

2

Мої два центи :)

приватний:

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

примірник змінної -> доступний лише у класі. Неможливо отримати доступ поза класом.

пакет-приватний:

class -> клас вищого рівня може бути приватним пакетом. Доступ до нього можна отримати лише з одного пакету. Не з підпакету, не з зовнішнього пакета.

екземпляр змінної -> доступний з одного пакета. Не з підпакету, не з зовнішнього пакета.

захищено:

class -> клас вищого рівня не можна захистити.

екземпляр змінної -> Доступний лише в тому ж пакеті або субпакеті. Доступ може бути тільки поза пакетом під час розширення класу.

загальнодоступний:

клас -> доступний з пакету / субпакету / іншого пакета

екземпляр змінної -> доступний з пакета / субпакету / іншого пакета

Ось детальна відповідь

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md


1
  • громадські

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

  • захищені

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

  • за замовчуванням

    У Java за замовчуванням НЕ є ключовим словом модифікатора доступу. Якщо член класу оголошено без будь-якого ключового слова модифікатора доступу, то в цьому випадку він вважається членом за замовчуванням. Член класу за замовчуванням завжди доступний тим самим членам класу пакунків. Але зовнішній член класу пакету НЕ може отримати доступ до стандартних членів класу, навіть якщо зовнішні класи є підкласами на відміну від захищених членів

  • приватний

    Якщо член класу оголошено захищеним ключовим словом, то в цьому випадку він доступний ТОЛЬКО тим самим членам класу


-1

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

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

Пакет-приватний (за замовчуванням) : Цей специфікатор доступу надаватиме доступ, визначений приватним специфікатором доступу, крім доступу, описаного нижче.

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

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

захищено : Цей специфікатор доступу забезпечить доступ, визначений специфікатором доступу приватного пакета на додаток до описаного нижче доступу.

Коли ви розробляєте якийсь пакет, а отже, і якийсь клас (скажімо, Class1) в ньому, вам слід використовувати захищений специфікатор доступу для члена даних класу Class1, якщо ви не хочете, щоб цей член отримав доступ поза вашим пакетом (скажімо, в пакеті споживача ваш пакет, тобто клієнт, який використовує ваші API), але ви хочете зробити виняток і дозволити доступ до цього члена лише в тому випадку, якщо клієнт пише клас скажіть Class2, який розширює Class1. Таким чином, як правило, захищені члени будуть доступні за посиланням "це" у похідних класах, тобто Class2, а також у явних екземплярах Class2.

Будь ласка, запиши:

  1. Ви не зможете отримати доступ до успадкованого захищеного члена Class1 у Class2, якщо ви спробуєте отримати доступ до нього в явному екземплярі Class1, хоча він успадкований у ньому.
  2. Коли ви пишете інший клас Class3 в межах одного / іншого пакету, що розширює Class2, захищений член від Class1 буде доступний у цій посиланні, а також у явній інстанції Class3. Це буде справедливо для будь-якої розширеної ієрархії, тобто захищений член все ще буде доступний у цій посиланні або екземплярі розширеного класу. Зауважте, що в Class3, якщо ви створюєте екземпляр Class2, ви не зможете отримати доступ до захищеного члена з Class1, хоча він успадковується.

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

public : Цей специфікатор доступу надаватиме доступ, визначений захищеним специфікатором доступу, крім доступу, описаного нижче.

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

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