В чем разница между общедоступным, защищенным, частным пакетом и частным в Java?

avatar
intrepion
18 октября 2008 в 19:53
2294656
30
3379

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

Источник
Museful
13 февраля 2013 в 09:56
176

private скрывается от других классов в пакете. public предоставляется классам вне пакета. protected - это версия public, ограниченная только подклассами.

Nicolas Barbulesco
21 августа 2013 в 09:51
97

@Tennenrishin - Нет; в отличие от C ++, в Java protected делает метод доступным из всего пакета. Эта глупость в модели видимости Java нарушает цель protected.

Museful
14 марта 2014 в 10:59
38

@Nicolas Доступен из всего пакета, с protected или без него. В качестве модификатора доступа все, что делает protected, - это предоставлять подклассам вне пакета.

luis.espinal
7 апреля 2014 в 13:45
17

@tennenrishin - ну, это то, что сказал Николас ... и вы просто повторяете это сейчас. Первоначально вы сказали, что protected - и я цитирую - «это версия public, ограниченная только подклассами», что неверно, по вашему собственному признанию, поскольку protected также разрешает доступ через весь пакет (следовательно, это не ограничить доступ к подклассам.)

luis.espinal
7 апреля 2014 в 13:53
14

Я также согласен с Николасом в том, что режим защищенного доступа в Java - это идиотизм. Случилось так, что Java объединила квалификаторы горизонтального (решетчатого) и вертикального ограничения доступа. Область действия по умолчанию - это ограничение по горизонтали / решетке, при этом решетка является пакетом. Public - еще одно горизонтальное ограничение, где решетка - это весь мир. Частные и (C ++) защищенные - вертикальные. Было бы лучше, если бы у нас был перекрестный доступ, скажем, protected-package для тех редких случаев, когда он нам действительно нужен, оставив protected эквивалентным защищенной версии C ++.

Museful
27 января 2015 в 19:43
8

@ luis.espinal Тогда он просто повторял то, что было сказано в первом комментарии. Вы не можете раскрыть то, что уже видно, и утверждение, что protected является ограниченным экспонентом, не означает, что он скрывает что-либо. В противном случае даже «public предоставляет классы вне пакета» будет означать, что public скрывает от классов внутри пакета.

E-Riz
1 сентября 2015 в 15:28
1

Принятый ответ не является неправильным, он просто неполный и простое задание копирования + вставки с внешнего ресурса. Ответ @Mechanical snail (coderhelper.com/a/12401576/639520) намного лучше IMO.

Malcolm
5 ноября 2015 в 16:39
3

@NicolasBarbulesco В отличие от C ++? В C ++ нет пакетов, вы не сможете сделать метод доступным для ряда классов, если не сделаете каждый из них другом класса вручную. Если бы в Java не было концепции пакетов, она работала бы точно так же. Говоря о глупости, код из одного и того же пакета в любом случае должен исходить от одного и того же разработчика, поэтому я не вижу здесь большой проблемы.

Nicolas Barbulesco
20 ноября 2015 в 10:02
1

@Malcolm - «код из одного и того же пакета в любом случае должен исходить от одного разработчика» Кто это сказал? Часто это не так.

Malcolm
20 ноября 2015 в 10:06
1

@NicolasBarbulesco Я не понимаю, как это возможно, если пакеты имеют правильный префикс домена разработчика.

NoName
23 июня 2017 в 08:42
2

Никто больше не заметил шутку, что модератор Mystical protected этот вопрос, чтобы не дать всем ответить ?? Гений!

Enerccio
18 мая 2018 в 07:12
0

@Malcolm, это неправда, мы регулярно помещаем наши собственные классы в те же пакеты, что и библиотеки, из-за частного доступа к пакету

Malcolm
18 мая 2018 в 13:28
0

@Enerccio Что не так? Я не говорил, что этого никто не делает. Однако это плохая практика: вы получаете доступ к некоторым частным API таким образом, что делает код хрупким, а начиная с Java 9 пакеты, разделенные по модулям, вообще не разрешены.

Enerccio
19 мая 2018 в 14:01
0

Частный пакет @Malcolm был просто плохой идеей, и у java его никогда не должно было быть. Недавно мне пришлось создать элемент JSON по умолчанию, который не будет генерировать NPE, если данные были нулевыми, но я не мог этого сделать, потому что один метод в JSONElement был закрытым для пакета. Так что мне пришлось обмануть это.

Malcolm
19 мая 2018 в 21:32
0

@Enerccio Я не понимаю, насколько неудобный дизайн API делает виноватым Java.

Enerccio
21 мая 2018 в 05:27
0

Ошибка @Malcolm java заключается в том, что есть частный пакет

Malcolm
21 мая 2018 в 09:41
0

@Enerccio Вы уже заявили об этом, но не привели аргументов. Мы можем продолжить в чате.

Ответы (30)

avatar
David Segonds
18 октября 2008 в 19:57
5965

Официальный учебник может быть вам полезен.


Класс Пакет Подкласс
(тот же пакет)
Подкласс
(diff pkg)
Мир
public + + + + +
protected + + + +
без модификатора + + +
private +

+: доступный
пусто: недоступно

niks
1 сентября 2017 в 08:35
31

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

Deepak
25 апреля 2018 в 12:25
2

Я до сих пор не могу различить «общедоступный» и «защищенный». И что в этом ответе «Мир». Означает ли это доступ из папки проекта в другом проекте и пакете ?? Но этого не происходит. Нужна помощь в этом.

adprocas
3 мая 2018 в 12:59
2

@Deepak, Мир в твоем проекте. Если у вас есть общедоступный класс, любой другой класс может создать его экземпляр. То же, что и методы. Если он общедоступный, любой, кто использует этот класс, может использовать этот метод. Пакет относится к «папке», в которой вы находитесь. Итак, ca.my.package.controllers отличается от ca.my.package.models. Общедоступные элементы доступны вне этих пакетов, а остальные - нет. package-private, по сути, считаются общедоступными в пакете. Защищенный означает все, что наследует его или находится в том же пакете. Private удаляет весь доступ извне, включая пакет.

adprocas
3 мая 2018 в 13:02
7

Мир внутри вашего проекта . Я должен объяснить дальше. Библиотеки находятся внутри вашего проекта, и если вы создаете библиотеку, они также будут предоставлять эти общедоступные классы и методы. Так что говорить только в рамках вашего проекта немного неуместно. «Все, кто его использует» - лучшее описание.

Deepak
4 мая 2018 в 06:23
1

@adpro - я попытался сделать методы общедоступными и защищенными, но оба этих типа методов доступны за пределами их основного пакета, и пользователь должен расширить родительский класс в обоих случаях, что совершенно очевидно. Я до сих пор не уверен в разнице. Может помочь еще немного объяснений или уловок.

adprocas
4 мая 2018 в 12:22
1

@Deepak, если вы расширяете (наследуете) класс, то этот наследующий класс будет иметь доступ ко всем общедоступным и защищенным методам и свойствам. Если вместо этого вы создадите экземпляр этого класса в другом классе (не расширяете) и попытаетесь сделать что-то вроде object.protectedMethod() в защищенном методе, вы не сможете этого сделать, если он не находится в том же пакете.

adprocas
4 мая 2018 в 12:25
5

Например, если у меня есть MyClass, а я делаю AnotherClass extends MyClass, у меня будет доступ ко всем защищенным и общедоступным методам и свойствам из AnotherClass. Если я где-нибудь сделаю MyClass myClass = new MyClass(); в AnotherClass - скажем, конструктор - у меня будет доступ к общедоступным методам, только если он находится в другом пакете. Обратите внимание: если я сделаю = new MyClass() { @Override protected void protectedMethod() { //some logic } };, окажется, что я могу получить доступ к защищенным методам, но это то же самое, что и расширение, но вместо этого встроено.

Dawood ibn Kareem
11 июля 2018 в 06:26
7

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

Anatolii Stepaniuk
6 сентября 2018 в 07:04
1

Поле подкласса (того же пакета) вводит в заблуждение, этот столбец лучше удалить. Потому что не имеет значения, подкласс или нет.

Heinzlmaen
6 февраля 2020 в 14:58
4

@DawoodsaysreinstateMonica Это отличный ответ, это именно то, что ищет большинство людей, которые находят эту страницу. Кроме того, эта таблица взята из официального руководства Oracle. Но как насчет того, чтобы дать нам ссылку, чтобы мы узнали, что на самом деле означает «защищенный»?

Badri Paudel
8 мая 2020 в 10:18
2

protected доступен только в том же пакете. Он недоступен вне этого пакета. Спецификатор protected в java называется спецификатором уровня пакета.

jayjay
29 июля 2020 в 22:44
1

@UsagiMiyamoto: Не могли бы вы подробнее рассказать о том, как «частные члены могут быть видны / использованы любым классом / статическим методом в одном и том же исходном файле»?

jayjay
29 июля 2020 в 22:46
3

@niks: я могу получить доступ к защищенным членам из подкласса разных пакетов

Jack
15 октября 2020 в 12:30
7

Доступ к защищенным членам @niks МОЖЕТ получить доступ подклассам из другого пакета. Разве не в этом суть? Иначе какая разница между по умолчанию и защищенным?

Piovezan
5 февраля 2021 в 02:57
5

@Jack Да, комментарий niks неверен, несмотря на то, что многие положительные отзывы говорят об обратном. Ссылка на учебные пособия по Java в ответе четко говорит, что к защищенным членам также можно получить доступ в подклассах из другого пакета. Похоже, он / она имел в виду «уровень пакета» вместо «защищенный» или имел в виду другое редактирование.

M. Justin
17 февраля 2021 в 07:38
2

@DawoodsaysreinstateMonica Я думаю, проблема здесь в том, что заголовок и тело задают два разных вопроса: «В чем разница между модификаторами доступа» и «Когда следует использовать разные модификаторы доступа». Этот ответ отвечает на вопрос в заголовке, но не на вопрос в теле.

Marco Sulla
5 июля 2021 в 12:37
0

@DawoodibnKareem, можете ли вы объяснить реальное функционирование protected или дать ссылку на страницу, которая объясняет это лучше?

Dawood ibn Kareem
6 июля 2021 в 00:21
0

@MarcoSulla К сожалению, 7 из первых 8 ответов на этой странице (в настоящее время) на самом деле неверны. Я просто проголосовал против этих 7, потому что считаю, что это большое дело. Взгляните на ответ инженера Фуада, который на данный момент является девятым на этой странице. Это первая действительно хорошая.

avatar
Yogesh Sharma
10 февраля 2022 в 15:17
1

используйте private, если вы не хотите, чтобы ваши переменные/методы/классы были видны за пределами этого класса. используйте protected, если вы хотите, чтобы только дочерние элементы этого класса могли использовать эти переменные. используйте public, если вы хотите, чтобы переменная/класс/метод были доступны из любого места. используйте package-private, если вы хотите, чтобы ваши переменные/классы/методы использовались только внутри этого пакета.

avatar
Mushfiqur Rahman Abir
12 сентября 2020 в 07:33
5

Differences between public, private, default and protected access modifiers

Это изображение поможет вам легко понять основные различия между модификаторами доступа public, private, protected и default. Модификатор по умолчанию применяется автоматически, если вы не объявляете в своем коде модификаторы доступа ant.

ahmednabil88
18 декабря 2020 в 20:56
2

Для большей ясности no modifier == package private | package protected

Mushfiqur Rahman Abir
15 марта 2021 в 15:05
0

Это хорошая демонстрация

avatar
Tushar Baviskar
23 декабря 2019 в 14:26
-1

Спецификаторы доступа в Java: В java есть 4 спецификатора доступа: private, package-private (по умолчанию), protected и public в порядке возрастания доступа.

Частный : Когда вы разрабатываете какой-либо класс и хотите, чтобы член этого класса не отображался за пределами этого класса, вы должны объявить его закрытым. к закрытым членам можно получить доступ только в том классе, в котором они определены, то есть охватывающем классе. доступ к закрытым членам можно получить по ссылке «this», а также по другим экземплярам класса, включающего эти элементы, но только в пределах определения этого класса.

Пакет-частный (по умолчанию) : Этот спецификатор доступа будет предоставлять доступ, указанный спецификатором частного доступа, в дополнение к доступу, описанному ниже.

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

По сути, в одном пакете вы можете получить доступ к элементам по умолчанию в экземпляре класса напрямую или по ссылке «this» в подклассах.

защищенный : Этот спецификатор доступа будет предоставлять доступ, указанный спецификатором доступа частного пакета, в дополнение к доступу, описанному ниже.

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

Обратите внимание:

  1. Вы не сможете получить доступ к унаследованному защищенному члену Class1 в Class2, если вы попытаетесь получить к нему доступ в явном экземпляре Class1, хотя он унаследован от него.
  2. Когда вы пишете другой класс Class3 в том же / другом пакете который расширяет Class2, защищенный член из Class1 будет доступен по этой ссылке, а также по явному экземпляру Class3. Это будет быть истинным для любой расширенной иерархии, т. е. защищенного члена будет по-прежнему доступен по этой ссылке или экземпляру расширенного учебный класс. Обратите внимание, что в Class3, если вы создаете экземпляр Class2, тогда вы не сможете получить доступ к защищенному члену из Class1, хотя он передается по наследству.

Итак, суть в том, что защищенные члены могут быть доступны в других пакетах, только если некоторый класс из этого другого пакета расширяет класс, включающий этот защищенный член, а защищенный член доступен по ссылке 'this' или явным экземплярам расширенного класс в пределах определения расширенного класса.

public : этот спецификатор доступа будет предоставлять доступ, указанный спецификатором защищенного доступа, в дополнение к доступу, описанному ниже.

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

avatar
yoAlex5
6 декабря 2019 в 20:42
8

Доступ к Java изменяет

enter image description here

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

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

Класс верхнего уровня (область первого уровня) может быть public и default. Nested class [О программе] может быть любой из них

package не применяется для иерархии пакетов

[Модификаторы быстрого доступа]

avatar
Mudassar
16 октября 2019 в 03:10
3

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

private:

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

переменная экземпляра -> доступна только в классе. Нет доступа вне класса.

частный пакет :

​​класс -> класс верхнего уровня может быть частным для пакета. Он может быть доступен только из того же пакета. Не из дополнительного пакета, не из внешнего пакета.

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

защищено :

класс -> класс верхнего уровня не может быть защищен.

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

общедоступный :

класс -> доступный из пакета / подпакета / другого пакета

переменная экземпляра -> доступна из пакета / подпакета / другого пакета

Вот подробный ответ

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

avatar
leonidaa
20 сентября 2019 в 07:28
2

private-protected-public-perfect-analogy-for-the-variable-data-types

Следующая блок-схема объясняет, как элементы данных базового класса унаследованы , когда производный класс <424378657806578> режим доступа <424737480780> private2480780>.

enter image description here

Примечание. Объявление элементов данных со спецификатором частного доступа известно как сокрытие данных.

Источник: Спецификаторы доступа - частные, общедоступные и защищенные

Benoit
20 сентября 2019 в 08:57
1

Речь шла о Java, а не о C ++.

leonidaa
22 сентября 2019 в 10:31
1

@Benoit Но то, что я опубликовал, особенно изображения, не одинаковы для обоих: java и c ++? Эти правила не применяются и для java? Благодарность

Benoit
23 сентября 2019 в 09:15
2

В C ++ модификаторов всего 3, а в java - 4.

mss
3 января 2020 в 09:54
1

аналогия хороша, но спецификатор доступа по умолчанию отсутствует,

JL_SO
9 апреля 2020 в 21:00
1

OP задал вопрос: «В чем разница между общедоступным, защищенным, частным пакетом и частным в Java?»

avatar
Vipul Verma
19 сентября 2019 в 22:34
1
  • общедоступный

    Если член класса объявлен как public, то к нему можно будет получить доступ из любого места

  • защищенный

    Если член класса объявлен с ключевым словом protected, то к нему можно получить доступ из тех же членов класса, вне членов класса в том же пакете и унаследованных членов класса. Если член класса защищен, то к нему НЕЛЬЗЯ получить доступ из внешнего класса пакета, если только внешний упакованный класс не унаследован, т.е. расширяет другой суперкласс пакета. Но член защищенного класса всегда доступен для одних и тех же классов пакетов, НЕ имеет значения, унаследован ли тот же класс пакета или НЕ

  • по умолчанию

    В Java по умолчанию НЕ используется ключевое слово модификатора доступа. Если член класса объявлен без ключевого слова модификатора доступа, то в этом случае он считается членом по умолчанию. Член класса по умолчанию всегда доступен для тех же членов класса пакета. Но внешний член класса пакета НЕ может получить доступ к членам класса по умолчанию, даже если внешние классы являются подклассами, в отличие от защищенных членов

  • частный

    Если член класса объявлен с ключевым словом protected, то в этом случае он доступен ТОЛЬКО для тех же членов класса

avatar
Christophe Roussy
14 февраля 2018 в 09:55
2

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

Начните с самого ограничительного (частного) и посмотрите, не понадобятся ли вам позже менее строгие модификаторы.

Мы все используем модификаторы методов и членов, такие как private, public, ... но очень немногие разработчики используют пакеты для логической организации кода .

Например: Вы можете поместить чувствительные методы безопасности в пакет «безопасности». Затем поместите общедоступный класс, который обращается к некоторому коду, связанному с безопасностью, в этом пакете, но оставьте другие классы безопасности пакетом закрытым . Таким образом, другие разработчики смогут использовать общедоступный класс только извне этого пакета (если они не изменят модификатор). Это не функция безопасности, но будет направлять использование.

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

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

Если, наоборот, вы установите все как public , будет непонятно, к чему следует или не следует обращаться, что может привести к написанию большого количества javadoc (который ничего не навязывает через компилятор. ..).

avatar
Pritam Banerjee
27 июня 2017 в 02:33
4

Когда вы думаете о модификаторах доступа, просто думайте об этом таким образом (применимо как к переменным , так и к методам ):

public -> доступный из любого места
private -> доступный только в том же классе, где он объявлен

Теперь возникает путаница, когда дело доходит до default и protected

default -> Нет ключевого слова модификатора доступа. Это означает, что он доступен строго внутри пакета класса. Нигде за пределами этого пакета к нему нельзя получить доступ.

protected -> Немного менее строгий, чем default, и, помимо тех же классов пакетов, к нему могут получить доступ подклассы за пределами пакета , который он объявлен.

avatar
Greedy Coder
6 апреля 2017 в 04:09
5

Часто я осознавал, что запоминание основных концепций любого языка стало возможным благодаря созданию аналогий из реального мира. Вот моя аналогия для понимания модификаторов доступа в Java:

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

  • Когда вы приводите его в кампус, первое, что вы и ваш друг видите, - это статуя. Это означает, что любой, кто ходит по кампусу, может смотреть на статую без разрешения университета. Это делает статую ОБЩЕСТВЕННОЙ .

  • Затем вы хотите отвести друга к себе в общежитие, но для этого вам нужно зарегистрировать его как посетителя. Это означает, что он получает пропуск (такой же, как у вас), чтобы попасть в различные здания на территории кампуса. Это сделает его карту доступа ЗАЩИЩЕННОЙ .

  • Ваш друг хочет войти в сеть Wi-Fi кампуса, но у него нет для этого учетных данных. Единственный способ, которым он может выйти в Интернет, - это если вы поделитесь с ним своим логином. (Помните, что каждый студент, поступающий в университет, также имеет эти учетные данные). Это сделает ваши учетные данные как NO MODIFIER .

  • Наконец, ваш друг хочет прочитать ваш отчет об успеваемости за семестр, который размещен на веб-сайте. Однако у каждого студента есть свой личный логин для доступа к этому разделу веб-сайта кампуса. Это сделает эти учетные данные как ЧАСТНЫЕ .

Надеюсь, это поможет!

avatar
ישו אוהב אותך
17 ноября 2016 в 05:05
6

Примечание: Это просто дополнение к принятому ответу.

Это связано с Java Модификаторами доступа.

Из Модификаторы доступа Java:

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

  • Элемент списка
  • частный
  • по умолчанию (пакет)
  • защищенный
  • общедоступный

Из Руководства по управлению доступом к членам класса:

Модификаторы уровня доступа определяют, могут ли другие классы использовать конкретное поле или вызвать определенный метод. Есть два уровня контроля доступа:

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

Класс может быть объявлен с модификатором public, и в этом случае class везде виден всем классам. Если у класса нет модификатора (по умолчанию, также известный как package-private), он виден только в собственном пакете

В следующей таблице показан доступ к элементам, разрешенный каждым модификатор.

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
║ 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     ║
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

Первый столбец данных указывает, имеет ли сам класс доступ к член, определенный уровнем доступа. Как видите, класс всегда имеет доступ к своим собственным участникам. Во втором столбце указано, классы в том же пакете, что и класс (независимо от их parentage) имеют доступ к члену. Третий столбец указывает имеют ли подклассы класса, объявленного вне этого пакета, доступ к члену. Четвертый столбец указывает, все ли классы иметь доступ к участнику.

Уровни доступа влияют на вас двояко. Во-первых, когда вы используете классы, поступают из другого источника, такого как классы на платформе Java, уровни доступа определяют, какие члены этих классов принадлежат вам классы могут использовать. Во-вторых, когда вы пишете класс, вам нужно решить какой уровень доступа для каждой переменной-члена и каждого метода в вашем классе должно быть.

sehe
17 ноября 2016 в 15:39
1

что именно представляет собой дополнение и почему это не редактирование существующего сообщения?

ישו אוהב אותך
18 ноября 2016 в 02:25
0

дополнение - Модификаторы доступа. Почему не редактировать? Оставить принятый ответ неизменным по историческим причинам и дать свой ответ.

avatar
Afee
7 августа 2016 в 14:16
17

Модификаторы доступа в 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();
  }
}

Вывод: Hello

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();
  }
}

Вывод: Hello

Enter image description here

avatar
aioobe
10 ноября 2015 в 10:27
476

Вот лучшая версия таблицы, которая также включает столбец для модулей.

Java Access Modifiers

Пояснения

  • частный элемент (i) только доступный в том же классе, что и объявлен.

  • Элемент с без модификатора доступа (j) доступен только внутри классов в том же пакете.

  • Элемент protected (k) доступен во всех классах одного пакета и в подклассах в подклассах других пакетов.

  • Элемент public (l) доступен для всех классов (если он не находится в модуле, который не экспортирует пакет), этот пакет объявлен.


Какой модификатор выбрать?

Модификаторы доступа - это инструмент, который поможет вам предотвратить случайное нарушение инкапсуляции (*) . Спросите себя, хотите ли вы, чтобы этот член был чем-то внутренним по отношению к классу, пакету, иерархии классов или вообще не внутренним, и выберите соответствующий уровень доступа.

Примеры :

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

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

GhostCat
11 октября 2018 в 10:50
19

Сразу скажу: есть много людей, у которых проблемы с различением красного / зеленого цветов. Таблицы, использующие схемы раскраски красный / зеленый (или желтый / оранжевый / ...) редко бывают "лучше" в чем-либо ;-)

aioobe
14 ноября 2018 в 14:10
5

@GhostCat, я не согласен. Я думаю, что красный / зеленый интуитивно сочетается с «работает» / «не работает» для многих людей, то есть лучше, чем многие альтернативы.

GhostCat
14 ноября 2018 в 14:13
11

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

aioobe
14 ноября 2018 в 14:32
7

@GhostCat Хорошо ... это большая часть населения, чем я ожидал. Я загрузил изображение в этот симулятор дальтонизма и протестировал все различные режимы. Даже в режиме монохромности / ахроматопсии разница в цвете разумная. Вы видите разницу или симулятор выключен? (Я по-прежнему считаю, что красный / зеленый очень интуитивно понятен для людей, видящих цвета.)

GhostCat
14 ноября 2018 в 14:40
5

Я вижу разницу, но я также могу пройти половину тестов на дальтонизм, которые мы должны сделать в Германии для получения водительских прав ;-) ... но я думаю, что такой симулятор «достаточно хорош».

avatar
Shailendra Singh
29 августа 2015 в 07:15
13
  • общедоступный - доступен из любой точки приложения.

  • по умолчанию - доступно из пакета.

  • защищенный - доступен из пакета и подклассов в другом пакете. а также

  • частный - доступен только из своего класса.

avatar
amila isura
26 мая 2015 в 14:54
13

Видно для пакета. По умолчанию. Модификаторы не нужны.

Виден только классу ( частный ).

Видно всему миру ( общедоступный ).

Виден пакету и всем подклассам ( защищенный ).

Переменные и методы можно объявлять без каких-либо вызываемых модификаторов. Примеры по умолчанию:

String name = "john";

public int age(){
    return age;
}

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

Методы, переменные и конструкторы, объявленные частными, доступны только внутри самого объявленного класса. Модификатор частного доступа - это самый ограничительный уровень доступа. Класс и интерфейсы не могут быть частными.

Переменные, объявленные частными, могут быть доступны вне класса, если в классе присутствуют общедоступные методы получения.

Использование модификатора private - это основной способ инкапсуляции объекта и скрытия данных от внешнего мира.

Примеры:

Public class Details{

    private String name;

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

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

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

Класс, метод, конструктор, интерфейс и т. Д., Объявленные общедоступными, могут быть доступны из любого другого класса. Следовательно, к полям, методам и блокам, объявленным внутри общедоступного класса, можно получить доступ из любого класса, принадлежащего вселенной Java.

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

Из-за наследования классов все общедоступные методы и переменные класса наследуются его подклассами.

Пример:

public void cal(){

}

Модификатор защищенного доступа - protected:

Переменные, методы и конструкторы, объявленные защищенными в суперклассе, могут быть доступны только подклассам в другом пакете или любому классу в пакете класса защищенных членов.

Модификатор защищенного доступа не может применяться к классу и интерфейсам. Методы и поля могут быть объявлены защищенными, однако методы и поля в интерфейсе не могут быть объявлены защищенными.

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}
avatar
Prashant
17 декабря 2014 в 06:29
16

Модификаторы доступа предназначены для ограничения доступа на нескольких уровнях.

Public: По сути, это так же просто, как вы можете получить доступ из любого класса, независимо от того, находится он в том же пакете или нет.

Для доступа, если вы находитесь в одном пакете, вы можете получить доступ напрямую, но если вы находитесь в другом пакете, вы можете создать объект класса.

По умолчанию: Он доступен в том же пакете из любого класса пакета.

Для доступа вы можете создать объект класса. Но вы не можете получить доступ к этой переменной вне пакета.

Защищено: вы можете получить доступ к переменным в том же пакете, а также к подклассу в любом другом пакете. так что в основном это по умолчанию + унаследованное поведение .

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

Частный: доступ может быть в том же классе.

В нестатических методах вы можете получить доступ напрямую из-за этой ссылки (также в конструкторах), но для доступа в статических методах вам необходимо создать объект класса.

avatar
richa_v
30 июля 2014 в 03:51
5

Public Protected Default и private являются модификаторами доступа.

Они предназначены для инкапсуляции или скрытия и отображения содержимого класса.

  1. Класс может быть общедоступным или по умолчанию
  2. Члены класса могут быть общедоступными, защищенными, заданными по умолчанию или частными.

Личное недоступно вне класса По умолчанию доступно только в пакете. Защищено как в пакете, так и в любом расширяющем его классе. Публикация открыта для всех.

Обычно переменные-члены определены как частные, но методы-члены являются общедоступными.

user207421
24 сентября 2016 в 03:13
0

Default не является модификатором доступа, а два других написаны с ошибками.

avatar
samkit shah
18 июня 2014 в 07:13
19

Частный : ограниченный доступ только для класса

По умолчанию (без модификатора) : ограниченный доступ к классу и пакету

Защищено : Ограниченный доступ к классу, пакету и подклассам (как внутри, так и вне пакета)

Общедоступный : доступен для класса, пакета (всех) и подклассов ... Короче говоря, везде.

avatar
Nambi
22 января 2014 в 13:08
29

Личное

  • Методы, переменные и конструкторы

Методы, переменные и конструкторы, объявленные частными, доступны только внутри самого объявленного класса.

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

Модификатор частного доступа - это самый ограничительный уровень доступа. Класс и интерфейсы не могут быть частными.

Примечание

Переменные, объявленные частными, могут быть доступны вне класса, если в классе присутствуют общедоступные методы получения. Переменные, методы и конструкторы, которые объявлены защищенными в суперклассе, могут быть доступны только подклассам в другом пакете или любому классу в пакете класса защищенных членов.


Защищено

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

Модификатор защищенного доступа не может применяться к классам и интерфейсам.

Методы и поля могут быть объявлены защищенными, однако методы и поля в интерфейсе не могут быть объявлены защищенными.

Примечание

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


Общедоступный

Класс, метод, конструктор, интерфейс и т. Д., Объявленные общедоступными, могут быть доступны из любого другого класса.

Следовательно, поля, методы и блоки, объявленные внутри общедоступного класса, могут быть доступны из любого класса, принадлежащего Java Universe.

  • Различные пакеты

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

Из-за наследования классов все общедоступные методы и переменные класса наследуются его подклассами.


По умолчанию - ключевое слово отсутствует:

Модификатор доступа по умолчанию означает, что мы не объявляем явно модификатор доступа для класса, поля, метода и т. Д.

  • В тех же пакетах

Переменная или метод, объявленные без модификатора управления доступом, доступны любому другому классу в том же пакете. Поля в интерфейсе неявно являются общедоступными static final, а методы в интерфейсе по умолчанию общедоступны.

Примечание

Мы не можем переопределить статические поля. Если вы попытаетесь переопределить, это не покажет никаких ошибок но это не работает то, что мы кроме.

Похожие ответы

Ссылки ссылки

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

avatar
Eng.Fouad
15 ноября 2013 в 20:06
49

Наиболее неправильно понимаемый модификатор доступа в 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
          }
      }
      
Eng.Fouad
15 ноября 2013 в 20:08
0

Object#clone() - это пример элемента protected.

cst1992
28 октября 2017 в 09:18
0

В чем разница между выполнением super.foo() и первой недопустимой ситуацией f.foo()?

skomisa
30 января 2018 в 17:55
1

@ cst1992 Это сбивает с толку, но см. Спецификацию языка Java 6.6.2: «Доступ к защищенному члену или конструктору объекта может быть получен извне пакета, в котором он объявлен, только кодом, который отвечает за реализацию этого объекта». В super.foo () ссылка «super» «непосредственно отвечает за реализацию», а ссылка «f» - нет. Почему? Потому что вы можете быть на 100% уверены, что «super» относится к типу «Отец», но не к «f»; во время выполнения это может быть какой-то другой подтип отца. См. docs.oracle.com/javase/specs/jls/se9/html/…

Dawood ibn Kareem
11 июля 2018 в 06:20
1

Приятно читать ответ от человека, который понимает protected. К сожалению, все другие ответы на этой странице, которые определяют protected, немного ошибаются.

Marco Sulla
6 июля 2021 в 07:47
0

Это не то, о чем говорится на официальном сайте Oracle: «Модификатор protected указывает, что элемент может быть доступен только в его собственном пакете (как в случае с package-private) и, кроме того, подклассом его класса. в другом пакете . " - docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

avatar
Abdull
9 января 2013 в 21:42
212
____________________________________________________________________
                | 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         |       ✔       |     ✘     |       ✘       |   ✘    
____________________________________________________________________
vanguard69
15 августа 2016 в 16:53
2

Стоит выразить словами: «Модификатор Protected делает объект доступным для других пакетов, тогда как модификатор default / no ограничивает доступ к тому же пакету»

Abdull
15 августа 2016 в 18:14
2

@ vanguard69, модификатор protected делает отмеченную вещь (класс, метод или поле) доступной для некоторого другого класса в каком-то другом пакете , только если указанный другой класс является подклассом класс, в котором объявлен этот protected - помеченный объект .

sehe
10 декабря 2017 в 12:24
0

"без субтитров"? "этот подкласс в другом пакете"? Хм. Я думал, что знаю Java.

avatar
Hoa Nguyen
18 декабря 2012 в 18:01
96

Практическое правило:

  • private: область действия класса.
  • default (или package-private): объем пакета.
  • protected: package scope + child (как package, но мы можем создать подклассы из разных пакетов). Модификатор protected всегда сохраняет отношение "родитель-потомок".
  • public: везде.

В результате, если разделить право доступа на три права:

  • (D) irect (вызов из метода внутри того же класса или через синтаксис «this»).
  • (R) ссылка (вызвать метод, используя ссылку на класс или синтаксис с точкой).
  • (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   |
+—————————————————+————————————+———————————+
avatar
Ravi
27 октября 2012 в 17:49
54

Очень коротко

  • public: доступен отовсюду.
  • protected: доступен классам того же пакета и подклассам, находящимся в любом пакете.
  • по умолчанию (модификатор не указан): доступен классам того же пакета.
  • private: доступно только в пределах того же класса.
avatar
Mechanical snail
13 сентября 2012 в 07:38
117

На самом деле это немного сложнее, чем показывает простая сетка. Сетка сообщает вам, разрешен ли доступ, но что именно составляет доступ? Кроме того, уровни доступа сложным образом взаимодействуют с вложенными классами и наследованием.

Доступ по умолчанию (определяемый отсутствием ключевого слова) также называется частный-пакет. Исключение: в интерфейсе отсутствие модификатора означает открытый доступ; модификаторы, отличные от общедоступных, запрещены. Константы перечисления всегда открыты.

Сводка

Разрешен ли доступ к члену с этим спецификатором доступа?

  • Член 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

Некоторые вопросы по теме:

MC Emperor
25 августа 2018 в 20:34
2

«другие модификаторы, кроме общедоступных, запрещены» - в Java 9 это уже не так: интерфейсы также могут иметь частные методы.

avatar
dameng
15 марта 2012 в 11:53
11

Эта страница хорошо описывает модификатор доступа protected & default

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

Но эти защищенные члены «доступны вне пакета только через наследование». то есть вы можете получить доступ к защищенному члену класса в его подклассе, присутствующем в каком-то другом пакете, напрямую, как если бы этот член присутствует в самом подклассе. Но этот защищенный член не будет доступен в подклассе вне пакета с помощью ссылки на родительский класс. ....

Anand
27 октября 2012 в 18:55
0

Просто добавьте следующее: «Как только дочерний элемент получает доступ к защищенному члену родительского класса, он становится закрытым (или, скорее, я бы сказал, специальным закрытым членом, который может быть унаследован подклассами подкласса) членом подкласса».

avatar
Dov Wasserman
19 октября 2008 в 03:18
9

Ответ Дэвида объясняет значение каждого модификатора доступа. Что касается того, когда использовать каждый из них, я бы предложил сделать общедоступными все классы и методы каждого класса, которые предназначены для внешнего использования (его API), а все остальное - частным.

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

avatar
Schwern
18 октября 2008 в 21:17
514

(Предостережение: я не программист на Java, я программист на Perl. Perl не имеет формальной защиты, возможно, поэтому я так хорошо понимаю проблему :))

Частный

Как вы могли подумать, только класс , в котором он объявлен, может видеть его.

Частный пакет

Его можно увидеть и использовать только в пакете , в котором он был объявлен. Это значение по умолчанию в Java (что некоторые считают ошибкой).

Защищено

Пакет Private + можно увидеть подклассам или членам пакета.

Общедоступный

Это может видеть каждый.

Опубликован

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

C ++ определяет дополнительный уровень, называемый «друг», и чем меньше вы об этом знаете, тем лучше.

Когда что использовать? Вся идея заключается в инкапсуляции, чтобы скрыть информацию. Насколько это возможно, вы хотите скрыть от пользователей детали того, как что-то делается. Почему? Потому что тогда вы можете изменить их позже и не нарушить чей-либо код. Это позволяет вам оптимизировать, реорганизовывать, изменять дизайн и исправлять ошибки, не беспокоясь о том, что кто-то использовал код, который вы только что переработали.

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

Если вы хотите, чтобы пользователи могли настраивать поведение, а не делать внутренние компоненты общедоступными, чтобы они могли их переопределять, часто лучше вложить эти кишки в объект и сделать этот интерфейс общедоступным. Таким образом они могут просто подключить новый объект. Например, если вы пишете проигрыватель компакт-дисков и хотите, чтобы бит «найти информацию об этом компакт-диске» можно было настроить, вместо того, чтобы делать эти методы общедоступными, вы бы поместили все эти функции в отдельный объект и сделали общедоступным только средство получения / установки объекта. . Таким образом, скупость на раскрытие своей кишки способствует хорошему составу и разделению проблем

Лично я придерживаюсь только «частных» и «общедоступных». Во многих объектно-ориентированных языках именно это есть. «Защищенный» может быть кстати, но на самом деле это обман. Как только интерфейс становится более чем частным, он выходит из-под вашего контроля, и вам нужно искать в чужом коде варианты использования.

Здесь появляется идея «опубликованного». Изменение интерфейса (его рефакторинг) требует, чтобы вы нашли весь код, который его использует, и изменили его тоже. Если интерфейс частный, нет проблем. Если он защищен, вам нужно найти все свои подклассы. Если он общедоступен, вам нужно найти весь код, который использует ваш код. Иногда это возможно, например, если вы работаете над корпоративным кодом, предназначенным только для внутреннего использования, не имеет значения, является ли интерфейс общедоступным. Вы можете взять весь код из корпоративного репозитория. Но если интерфейс «опубликован», если есть код, использующий его вне вашего контроля, то вы попали в беду. Вы должны поддерживать этот интерфейс, иначе вы рискуете взломать код. Даже защищенные интерфейсы можно считать опубликованными (поэтому я не заморачиваюсь с защищенными).

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

Sebastian Mach
7 июня 2011 в 10:13
27

друзья -> «Чем меньше вы об этом знаете, тем лучше» ---> Это дает выборочную видимость, которая по-прежнему превосходит конфиденциальность пакетов. В C ++ это имеет свое применение, потому что не все функции могут быть функциями-членами, а друзья лучше, чем общедоступные. Конечно, есть опасность злоупотребления злыми умами.

Rhys van der Waerden
2 октября 2011 в 12:34
33

Следует также отметить, что «защищенный» в C ++ имеет другое значение - защищенный метод фактически является закрытым, но все же может вызываться из наследующего класса. (В отличие от Java, где он может вызываться любым классом в одном пакете.)

Konrad Morawski
15 октября 2013 в 17:36
9

@RhysvanderWaerden C # в этом аспекте совпадает с C ++. Мне кажется довольно странным, что Java не позволяет объявлять член, доступный для подкласса, но не для всего пакета. Для меня это вроде как перевернутое - пакет шире, чем дочерний класс!

Eponymous
22 мая 2014 в 20:37
15

Пакет @KonradMorawski IMHO имеет меньшую область действия, чем подкласс. Если вы не объявили свой класс final, пользователи должны иметь возможность создавать подклассы, поэтому защита java является частью вашего опубликованного интерфейса. OTOH, пакеты неявно разрабатываются одной организацией: например, com.mycompany.mypackage. Если ваш код объявляется в моем пакете, вы неявно объявляете себя частью моей организации, поэтому мы должны общаться. Таким образом, пакет публикуется для меньшей / более доступной аудитории (люди в моей компании), чем подкласс (люди, которые расширяют мой объект), и поэтому считается более низкой видимостью.

Khaled.K
28 мая 2014 в 05:36
1

friend подходит только для особых случаев, таких как классы перегрузки. в противном случае это плохая практика для архитектурного дизайна, так как это испортит концепцию многоуровневости

Dennis
8 декабря 2014 в 10:05
2

friend удобен для определения особых отношений между классами. Во многих случаях при правильном использовании он обеспечивает превосходную инкапсуляцию. Например, он может использоваться привилегированным классом фабрики для внедрения внутренних зависимостей в сконструированный тип. У него плохая репутация, потому что люди, которые не заботятся о правильной поддержке хорошо спроектированной объектной модели, могут злоупотреблять ею, чтобы облегчить свою рабочую нагрузку.

Tomas
29 октября 2015 в 10:45
0

@ konrad-morawski В очень древние времена (до 1.03) Java имела дополнительный модификатор доступа private protected, который делал именно это. Было несколько причин, по которым он был удален, но основная, на мой взгляд, заключается в том, что пакет в Java ​​ действительно имеет более узкую область, чем дочерний класс (который обычно находится в каком-то другом пакете), поэтому этот доступ сделал нет реального смысла. Я на самом деле использовал его пару раз тогда, но так и не нашел подходящего случая для его использования. Я виню свои корни C ++ :)

User
8 октября 2016 в 09:48
0

В Java private предотвращает переопределения, protected - нет (но также не полностью публично), поэтому все они имеют свое применение.

maaartinus
10 июня 2017 в 09:24
0

«Как только интерфейс становится более чем частным, он выходит за рамки вашего контроля» - это верно только для тех, кто игнорирует видимость пакетов, как и вы. Все модификаторы важны для сокрытия информации, и пакет обычно создается небольшой тесно сотрудничающей командой, которая рассматривает все видимые методы пакета как частные для них. +++ Точно так же friend не предназначен для того, чтобы нанести ущерб видимости, но позволяет еще больше ужесточить правила при добавлении исключения (любой механизм исключения подвержен злоупотреблениям; поэтому видимость пакетов лучше, но, возможно, однажды месяц я тоже мог использовать friend).

avatar
Joe Phillips
18 октября 2008 в 20:00
20

Разницу можно найти в уже предоставленных ссылках, но какая из них обычно сводится к «Принципу наименьшего знания». Обеспечьте минимальную видимость, которая необходима.

avatar
John Nilsson
18 октября 2008 в 20:00
169

Простое правило. Начните с объявления всего приватным. А затем продвижение к публике по мере возникновения потребностей и того, что того требует дизайн.

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

Как правило, я стараюсь избегать переопределения реализаций методов путем создания подклассов; слишком легко запутать логику. Объявите абстрактные защищенные методы, если вы намереваетесь их переопределить.

Также используйте аннотацию @Override при переопределении, чтобы не допустить поломки при рефакторинге.

Andrejs
26 февраля 2016 в 19:12
4

@RuchirBaronia, "world" = весь код в приложении, независимо от того, где он находится.