Есть ли в Java четкие правила относительно того, когда использовать каждый из модификаторов доступа, а именно значение по умолчанию (частный пакет), public, protected и private, при создании class и interface и работе с наследованием?
@Tennenrishin - Нет; В отличие от C++, в Java protected делает этот метод доступным также из всего пакета. Эта глупость в модели видимости Java нарушает цель protected.
@Nicolas Доступен из всего пакета, с protected или без него. В качестве модификатор доступа все, что делает protected, - это предоставлять подклассам вне пакета.
@tennenrishin - ну, это то, что сказал Николас ... и вы просто повторяете это сейчас. Первоначально вы сказали, что protected - и я цитирую - `` это версия public, ограниченная только подклассами '', что неверно, по вашему собственному признанию, поскольку protected также разрешает доступ через весь пакет (следовательно, он не предоставляет ограничивать доступ к подклассам .)
Я также согласен с Николасом в том, что режим защищенного доступа в Java - это идиотизм. Случилось так, что Java объединила квалификаторы горизонтального (решетчатого) и вертикального ограничения доступа. Область действия по умолчанию - это ограничение по горизонтали / решетке, при этом решетка является пакетом. Public - еще одно горизонтальное ограничение, где решетка - это весь мир. Частные и (C++) защищенные - вертикальные. Было бы лучше, если бы у нас был сквозной доступ, скажем, protected-package для тех редких случаев, когда он нам действительно нужен, оставив protected эквивалентным защищенной версии C++.
@ luis.espinal Тогда он просто повторял то, что было сказано в первом комментарии. Вы не можете раскрыть то, что уже видно, и утверждение, что protected является ограниченным экспонентом, не означает, что это прячется что-то. В противном случае даже «public предоставляет классы вне пакета» будет означать, что publicпрячется из классов внутри пакета.
Принятый ответ не является неправильным, он просто неполный и простое задание копирования + вставки с внешнего ресурса. Ответ @Mechanical snail (stackoverflow.com/a/12401576/639520) намного лучше IMO.
@NicolasBarbulesco В отличие от C++? В C++ нет пакетов, вы не сможете сделать метод доступным для ряда классов, если не сделаете каждый из них другом класса вручную. Если бы в Java не было концепции пакетов, она работала бы точно так же. Говоря о глупости, код из одного и того же пакета в любом случае должен исходить от одного и того же разработчика, поэтому я не вижу здесь большой проблемы.
@Malcolm - «код из одного и того же пакета в любом случае должен исходить от одного разработчика» Кто это сказал? Часто это не так.
@NicolasBarbulesco Я не понимаю, как это возможно, если пакеты имеют правильный префикс домена разработчика.
Больше никто не заметил прикол, что модератор Mystical protected на этот вопрос не дает ответить все ?? Гений!
@Malcolm, это неправда, мы регулярно помещаем наши собственные классы в те же пакеты, что и библиотеки, из-за частного доступа к пакету
@Enerccio Что не так? Я не говорил, что этого никто не делает. Это плохая практика, вы получаете доступ к некоторым частным API таким образом, что делает код хрупким, а начиная с Java 9 пакеты, разделенные по модулям, вообще не разрешены.
Частный пакет @Malcolm был просто плохой идеей, и у java никогда не должно было быть такого. Недавно мне пришлось создать элемент JSON по умолчанию, который не будет генерировать NPE, если данные были нулевыми, но я не мог этого сделать, потому что один метод в JSONElement был закрытым для пакета. Так что мне пришлось обмануть это.
@Enerccio Я не понимаю, насколько неудобный дизайн API делает это ошибкой Java.
@Malcolm java виноват в том, что есть частный пакет
@Enerccio Вы уже заявили об этом, но не привели аргументов. Мы можем продолжить в чате.




Официальный учебник может быть вам полезен.
| Класс | Упаковка | Подкласс (тот же пакет) | Подкласс (diff pkg) | Мир | |
|---|---|---|---|---|---|
public | + | + | + | + | + |
protected | + | + | + | + | |
| без модификатора | + | + | + | ||
private | + |
+: доступно
пусто: недоступно
Доступ к защищенному члену можно получить только из подкласса того же пакета, но не из подкласса из другого пакета. В таблице выше должно быть исправление.
Я до сих пор не могу различить «общедоступный» и «защищенный». И что в этом ответе «Мир». Означает ли это доступ из папки проекта в другом проекте и пакете ?? Но этого не происходит. Нужна помощь в этом.
@Deepak, Мир в твоем проекте. Если у вас есть общедоступный класс, любой другой класс может создать его экземпляр. То же, что и методы. Если он открыт, любой, кто использует этот класс, может использовать этот метод. Пакет относится к «папке», в которой вы находитесь. Итак, ca.my.package.controllers отличается от ca.my.package.models. Общедоступные элементы доступны вне этих пакетов, а остальные - нет. package-private, по сути, считаются общедоступными в пакете. Защищенный означает все, что наследует его или находится в том же пакете. Private удаляет весь доступ извне, включая пакет.
@adpro - я попытался сделать методы общедоступными и защищенными, но оба этих типа методов доступны за пределами их основного пакета, и пользователь должен расширить родительский класс в обоих случаях, что совершенно очевидно. Я до сих пор не уверен в разнице. Может помочь еще немного объяснений или уловок.
@Deepak, если вы расширяете (наследуете) класс, то этот наследующий класс будет иметь доступ ко всем общедоступным и защищенным методам и свойствам. Если вместо этого вы создадите экземпляр этого класса в другом классе (не расширяете) и попытаетесь сделать что-то вроде object.protectedMethod() для защищенного метода, вы не сможете этого сделать, если он не находится в том же пакете.
Например, если у меня есть MyClass, а я использую AnotherClass extends MyClass, у меня будет доступ ко всем защищенным и общедоступным методам и свойствам из AnotherClass. Если я где-нибудь сделаю MyClass myClass = new MyClass(); в AnotherClass - скажем, конструктор - у меня будет доступ к общедоступным методам, только если он находится в другом пакете. Обратите внимание, что если я использую = new MyClass() { @Override protected void protectedMethod() { //some logic } };, похоже, что я могу получить доступ к защищенным методам, но это то же самое, что и расширение, но вместо этого встроено.
К сожалению, этот ответ является большим упрощением. Реальность немного сложнее, особенно если учесть protected (который на самом деле является довольно сложным модификатором доступа для полного понимания - большинство людей, которые думают, что знают, что означает protected, на самом деле не знают). Кроме того, как указал Богемиан, он не отвечает на вопрос - он говорит ничего такого о том, когда использовать каждый модификатор доступа. На мой взгляд, этот ответ не настолько плох, чтобы проголосовать против довольно, но близко. Но более 4000 голосов за? Как это произошло?
Поле подкласса (того же пакета) вводит в заблуждение, этот столбец лучше удалить. Потому что не имеет значения, подкласс или нет.
@DawoodsaysreinstateMonica Это отличный ответ, это именно то, что ищет большинство людей, которые находят эту страницу. Кроме того, эта таблица взята из официального руководства Oracle. Но как насчет того, чтобы дать нам ссылку, чтобы мы узнали, что на самом деле означает «защищенный»?
protected доступен только в том же пакете. Он недоступен вне этого пакета. Спецификатор protected в Java называется спецификатором уровня пакета.
@UsagiMiyamoto: Не могли бы вы подробнее рассказать о том, как «частные члены могут быть видны / использованы любым классовым / статическим методом в одном и том же исходном файле»?
@niks: я могу получить доступ к защищенным членам из подкласса разных пакетов
Доступ к защищенным членам @niks МОЖЕТ получить доступ подклассам из другого пакета. Разве не в этом суть? Иначе какая разница между по умолчанию и защищенным?
@Jack Да, комментарий niks неверен, несмотря на то, что многие положительные отзывы говорят об обратном. Ссылка на учебные пособия по Java в ответе четко говорит, что к защищенным членам также можно получить доступ в подклассах из другого пакета. Похоже, он / она имел в виду «уровень пакета» вместо «защищенный» или имел в виду другое редактирование.
@DawoodsaysreinstateMonica Я думаю, что проблема здесь в том, что заголовок и тело задают два разных вопроса: «В чем разница между модификаторами доступа» и «Когда следует использовать разные модификаторы доступа». Этот ответ отвечает на вопрос в заголовке, но не на вопрос в теле.
Простое правило. Начните с объявления всего приватным. А затем продвигайтесь к общественности по мере возникновения потребностей и того, что того требует дизайн.
Разоблачая участников, спросите себя, раскрываете ли вы варианты представления или варианты абстракции. Первое - это то, чего вы хотите избежать, так как это приведет к слишком большому количеству зависимостей от фактического представления, а не от его наблюдаемого поведения.
Как правило, я стараюсь избегать переопределения реализаций методов путем создания подклассов; слишком легко запутать логику. Объявите абстрактные защищенные методы, если вы намереваетесь их переопределить.
Кроме того, используйте аннотацию @Override при переопределении, чтобы не допустить поломки при рефакторинге.
@RuchirBaronia, "world" = весь код в приложении, независимо от того, где он находится.
Разницу можно найти в уже предоставленных ссылках, но какая из них обычно сводится к «Принципу наименьшего знания». Обеспечьте минимальную видимость, которая необходима.
(Предостережение: я не программист на Java, я программист на Perl. Perl не имеет формальной защиты, возможно, поэтому я так хорошо понимаю проблему :))
Как вы могли подумать, его может увидеть только класс, в котором он объявлен.
Его можно увидеть и использовать только тем упаковка, в котором он был объявлен. Это значение по умолчанию в Java (что некоторые считают ошибкой).
Пакет Private + можно увидеть подклассам или членам пакета.
Это все видят.
Виден за пределами контролируемого мной кода. (Хотя это и не синтаксис Java, он важен для этого обсуждения).
C++ определяет дополнительный уровень, называемый «друг», и чем меньше вы об этом знаете, тем лучше.
Когда что использовать? Вся идея заключается в инкапсуляции, чтобы скрыть информацию. Насколько это возможно, вы хотите скрыть от пользователей детали того, как что-то делается. Почему? Потому что тогда вы можете изменить их позже и не нарушить чей-либо код. Это позволяет вам оптимизировать, реорганизовывать, изменять дизайн и исправлять ошибки, не беспокоясь о том, что кто-то использовал код, который вы только что переработали.
Итак, практическое правило - делать вещи настолько видимыми, насколько они должны быть. Начните с приватного и добавляйте больше видимости только по мере необходимости. Публикуйте только то, что абсолютно необходимо пользователю, каждая деталь, которую вы публикуете, ограничивает вашу способность переделывать систему.
Если вы хотите, чтобы пользователи могли настраивать поведение, а не делать внутренние компоненты общедоступными, чтобы они могли их переопределить, часто лучше вложить эти кишки в объект и сделать этот интерфейс общедоступным. Таким образом, они могут просто подключить новый объект. Например, если вы пишете проигрыватель компакт-дисков и хотите, чтобы бит «найти информацию об этом компакт-диске» можно было настроить, вместо того, чтобы делать эти методы общедоступными, вы бы поместили всю эту функциональность в отдельный объект и сделали общедоступным только средство получения / установки объекта. . Таким образом, скупость на раскрытие своей интуиции способствует хорошему составу и разделению проблем.
Лично я придерживаюсь только «частных» и «общедоступных». Во многих объектно-ориентированных языках именно это есть. «Защищенный» может быть кстати, но на самом деле это обман. Как только интерфейс становится более чем частным, он выходит из-под вашего контроля, и вам нужно искать в чужом коде способы его использования.
Вот здесь-то и появляется идея «опубликованного». Для изменения интерфейса (его рефакторинга) необходимо найти весь код, который его использует, и изменить его. Если интерфейс частный, нет проблем. Если он защищен, вам нужно найти все свои подклассы. Если он общедоступен, вам нужно найти весь код, который использует ваш код. Иногда это возможно, например, если вы работаете над корпоративным кодом, предназначенным только для внутреннего использования, не имеет значения, является ли интерфейс общедоступным. Вы можете взять весь код из корпоративного репозитория. Но если интерфейс «опубликован», если есть код, использующий его вне вашего контроля, то вы попали в беду. Вы должны поддерживать этот интерфейс, иначе вы рискуете взломать код. Даже защищенные интерфейсы можно считать опубликованными (поэтому я не заморачиваюсь с защищенными).
Многие языки считают иерархическую природу общедоступного / защищенного / частного слишком ограничивающей и не соответствующей действительности. Для этого есть концепция класс черты, но это уже другое шоу.
друзья -> «Чем меньше вы об этом знаете, тем лучше» ---> Это дает выборочную видимость, которая по-прежнему превосходит конфиденциальность пакетов. В C++ это имеет свое применение, потому что не все функции могут быть функциями-членами, а друзья лучше, чем общедоступные. Конечно, есть опасность злоупотребления злыми умами.
Следует также отметить, что «защищенный» в C++ имеет другое значение - защищенный метод фактически является закрытым, но все же может вызываться из наследующего класса. (В отличие от Java, где он может вызываться любым классом в одном пакете.)
@RhysvanderWaerden C# в этом аспекте совпадает с C++. Мне кажется довольно странным, что Java не позволяет объявлять член, доступный для подкласса, но не для всего пакета. Для меня это вроде как перевернутое - пакет шире, чем дочерний класс!
Пакет @KonradMorawski IMHO имеет меньшую область действия, чем подкласс. Если вы не объявили свой класс final, пользователи должны иметь возможность создавать подклассы, поэтому защита java является частью вашего опубликованного интерфейса. OTOH, пакеты неявно разрабатываются одной организацией: например, com.mycompany.mypackage. Если ваш код объявляется в моем пакете, вы неявно объявляете себя частью моей организации, поэтому мы должны общаться. Таким образом, пакет публикуется для меньшей / более доступной аудитории (люди в моей компании), чем подкласс (люди, которые расширяют мой объект), и поэтому считается более низкой видимостью.
friend подходит только для особых случаев, таких как классы перегрузки. в противном случае это плохая практика для архитектурного дизайна, так как это испортит концепцию многоуровневостиfriend хорош для определения особых отношений между классами. Во многих случаях при правильном использовании он обеспечивает превосходную инкапсуляцию. Например, он может использоваться привилегированным классом фабрики для внедрения внутренних зависимостей в сконструированный тип. У него плохая репутация, потому что люди, которые не заботятся о правильной поддержке хорошо спроектированной объектной модели, могут злоупотреблять ею, чтобы облегчить свою рабочую нагрузку.@ konrad-morawski В очень древние времена (до 1.03) Java имела дополнительный модификатор доступа private protected, который делал именно это. Было несколько причин, по которым он был удален, но основная, на мой взгляд, заключается в том, что пакет в Java является действительно имеет более узкую область действия, чем дочерний класс (который обычно находится в каком-то другом пакете), поэтому этот доступ не имел реального смысла. Я на самом деле использовал его пару раз тогда, но так и не нашел подходящего случая для его использования. Я виню свои корни C++ :)
В Java private предотвращает переопределения, protected - нет (но также не полностью публично), поэтому все они имеют свое применение.
«Как только интерфейс становится более чем частным, он выходит за рамки вашего контроля» - это верно только для тех, кто игнорирует видимость пакетов, как и вы. Все модификаторы важны для сокрытия информации, и пакет обычно создается небольшой тесно сотрудничающей командой, которая рассматривает все видимые методы пакета как частные для них. +++ Точно так же friend не предназначен для того, чтобы нанести ущерб видимости, но позволяет еще больше ужесточить правила при добавлении исключения (любой механизм исключения подвержен злоупотреблениям; поэтому видимость пакетов лучше, но, возможно, раз в месяц я тоже можно использовать friend).
Ответ Дэвида объясняет значение каждого модификатора доступа. Что касается того, когда использовать каждый из них, я бы предложил сделать общедоступными все классы и методы каждого класса, которые предназначены для внешнего использования (его API), а все остальное - частным.
Со временем вы научитесь понимать, когда делать некоторые классы закрытыми для пакетов, а когда объявлять определенные методы защищенными для использования в подклассах.
Эта страница хорошо описывает модификатор доступа по умолчанию и защищенный
.... Защищено: модификатор защищенного доступа немного сложен и, можно сказать, является надмножеством модификатора доступа по умолчанию. Защищенные члены такие же, как члены по умолчанию, что касается доступа в том же пакете. Разница в том, что защищенные члены также доступны для подклассов класса, в котором объявлен член, которые находятся за пределами пакета, в котором присутствует родительский класс.
Но эти защищенные члены «доступны вне пакета только через наследование». то есть вы можете получить доступ к защищенному члену класса в его подклассе, присутствующем в каком-то другом пакете, напрямую, как если бы этот член присутствует в самом подклассе. Но этот защищенный член не будет доступен в подклассе вне пакета с помощью ссылки на родительский класс. ....
Просто добавьте следующее: «Как только дочерний элемент получает доступ к защищенному члену родительского класса, он становится закрытым (или, скорее, я бы сказал, специальным закрытым членом, который может быть унаследован подклассами подкласса) членом подкласса».
На самом деле это немного сложнее, чем показывает простая сетка. Сетка сообщает вам, разрешен ли доступ, но что именно составляет доступ? Кроме того, уровни доступа сложным образом взаимодействуют с вложенными классами и наследованием.
Доступ «по умолчанию» (определяемый отсутствием ключевого слова) также называется пакет-частный. Исключение: в интерфейсе отсутствие модификатора означает открытый доступ; модификаторы, отличные от public, запрещены. Константы перечисления всегда открыты.
Разрешен ли доступ к члену с этим спецификатором доступа?
private: только если член определен в том же классе, что и вызывающий код.protected: тот же пакет, или если член определен в суперклассе класса, содержащего вызывающий код.public: Да.Локальные переменные и формальные параметры не могут принимать спецификаторы доступа. Поскольку они по своей природе недоступны извне в соответствии с правилами области видимости, они фактически являются частными.
Для классов в верхней области разрешены только public и package-private. Этот выбор конструкции предположительно обусловлен тем, что protected и private будут избыточными на уровне пакета (нет наследования пакетов).
Все спецификаторы доступа возможны для членов класса (конструкторы, методы и статические функции-члены, вложенные классы).
Связанный: Доступность класса Java
Спецификаторы доступа могут быть строго упорядочены
public > protected > package-private > private
Это означает, что public обеспечивает наибольший доступ, а private - наименьший. Любая ссылка, возможная на частном члене, также действительна для частного члена пакета; любая ссылка на частный член пакета действительна для защищенного члена и т. д. (Предоставление доступа к защищенным членам другим классам в том же пакете считалось ошибкой.)
private[this].)Вы также должны учитывать области действия вложенный, такие как внутренние классы. Примером сложности является то, что внутренние классы имеют члены, которые сами могут принимать модификаторы доступа. Таким образом, у вас может быть частный внутренний класс с открытым членом; можно получить доступ к члену? (См. Ниже.) Общее правило - смотреть на область видимости и думать рекурсивно, чтобы увидеть, можете ли вы получить доступ к каждому уровню.
Однако это довольно сложно, и для получения полной информации используйте обратитесь к Спецификации языка 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
Некоторые связанные вопросы:
Очень коротко
public: доступен отовсюду.protected: доступен классам одного и того же пакета и подклассам, находящимся в любом пакете.private: доступен только в том же классе.Как правило большого пальца:
private: объем класса.default (или package-private): объем пакета.protected: package scope + child (как package, но мы можем создать подклассы из разных пакетов). Модификатор protected всегда сохраняет отношения «родитель-потомок».public: везде.В результате, если мы разделим право доступа на три права:
тогда у нас есть эта простая таблица:
+—-———————————————+————————————+———————————+
| | Same | Different |
| | Package | Packages |
+—————————————————+————————————+———————————+
| private | D | |
+—————————————————+————————————+———————————+
| package-private | | |
| (no modifier) | D R I | |
+—————————————————+————————————+———————————+
| protected | D R I | I |
+—————————————————+————————————+———————————+
| public | D R I | R I |
+—————————————————+————————————+———————————+
____________________________________________________________________
| 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 | ✔ | ✘ | ✘ | ✘
____________________________________________________________________
Стоит выразить словами: «Модификатор Protected делает объект доступным для других пакетов, тогда как модификатор default / no ограничивает доступ к тому же пакету»
@ vanguard69, модификатор protected делает отмеченный предмет (класс, метод или поле) доступным для некоторого другого класса в каком-то другом пакете. только тогда и только тогда говорит, что другой класс является подклассом класса, в котором объявлен этот помеченный protectedпредмет.
"без субтитров"? "этот подкласс в другом пакете"? Хм. Я думал, что знаю Java.
@AlexanderFarber вы оптимизировали для конкретной конфигурации браузера? Это мой хром сейчас, а это Fire Fox
Хм, давай вернем мои изменения
Точки для диаграммы ascii я могу вставить в текстовый файл заметок.
Наиболее неправильно понимаемый модификатор доступа в 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-х контекстах:
Внутри класса, который находится в том же пакете, где определен foo() (fatherpackage):
package fatherpackage;
public class SomeClass
{
public void someMethod(Father f, Son s)
{
f.foo();
s.foo();
}
}
Внутри подкласса в текущем экземпляре через this или super:
package sonpackage;
public class Son extends Father
{
public void sonMethod()
{
this.foo();
super.foo();
}
}
Для ссылки того же класса:
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();
}
}
Для ссылки, тип которой является родительским классом, и это внутри, пакет, в котором определен foo() (fatherpackage) [Это может быть включено в контекст №. 1]:
package fatherpackage;
public class Son extends Father
{
public void sonMethod(Father f)
{
f.foo();
}
}
Следующие ситуации недопустимы.
Для ссылки, тип которой является родительским классом, а это вне - пакет, в котором определен foo() (fatherpackage):
package sonpackage;
public class Son extends Father
{
public void sonMethod(Father f)
{
f.foo(); // compilation error
}
}
Неподкласс внутри пакета подкласса (подкласс наследует защищенные члены от своего родителя и делает их частными для не подклассов):
package sonpackage;
public class SomeClass
{
public void someMethod(Son s) throws Exception
{
s.foo(); // compilation error
}
}
Object#clone() является примером члена protected.В чем разница между выполнением super.foo() и первой недопустимой ситуацией f.foo()?
@ cst1992 Это сбивает с толку, но см. Спецификацию языка Java 6.6.2: «Доступ к защищенному члену или конструктору объекта может быть получен извне пакета, в котором он объявлен, только кодом, который отвечает за реализацию этого объекта». В super.foo () ссылка «super» «напрямую отвечает за реализацию», а ссылка «f» - нет. Почему? Потому что вы можете быть на 100% уверены, что «super» относится к типу «Отец», но не к «f»; во время выполнения это может быть какой-то другой подтип отца. См. docs.oracle.com/javase/specs/jls/se9/html/…
Приятно читать ответ человека, разбирающегося в protected. К сожалению, все остальные ответы на этой странице, которые определяют protected, немного ошибаются.
Доступ к методам, переменным и конструкторам, которые объявлены частными, можно получить только внутри самого объявленного класса.
Модификатор частного доступа - это самый ограничительный уровень доступа. Класс и интерфейсы не могут быть частными.
Примечание
Переменные, которые объявлены частными, могут быть доступны вне класса, если в классе присутствуют общедоступные методы получения.
Переменные, методы и конструкторы, которые объявлены защищенными в суперклассе, могут быть доступны только подклассам в другом пакете или любому классу в пакете класса защищенных членов.
Модификатор защищенного доступа нельзя применять к классу и интерфейсам.
Методы и поля могут быть объявлены защищенными, однако методы и поля в интерфейсе не могут быть объявлены защищенными.
Примечание
Защищенный доступ дает подклассу возможность использовать вспомогательный метод или переменную, предотвращая попытки несвязанного класса использовать их.
Доступ к классу, методу, конструктору, интерфейсу и т. д., Объявленному как общедоступный, можно получить из любого другого класса.
Следовательно, поля, методы и блоки, объявленные внутри общедоступного класса, могут быть доступны из любого класса, принадлежащего Java Universe.
Однако, если публичный класс, к которому мы пытаемся получить доступ, находится в другом пакете, то публичный класс все равно необходимо импортировать.
Из-за наследования классов все общедоступные методы и переменные класса наследуются его подклассами.
Модификатор доступа по умолчанию означает, что мы явно не объявляем модификатор доступа для класса, поля, метода и т. д.
Переменная или метод, объявленные без модификатора управления доступом, доступны любому другому классу в том же пакете. Поля в интерфейсе неявно являются общедоступными static final, а методы в интерфейсе по умолчанию общедоступны.
Примечание
Мы не можем переопределить статические поля. Если вы попытаетесь переопределить, это не покажет никаких ошибок но не работает то, что мы кроме.
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.htmlhttp://www.tutorialspoint.com/java/java_access_modifiers.htm
Частный: Ограниченный доступ только к классу
По умолчанию (без модификатора): Ограниченный доступ к классу и пакету
Защищено: ограниченный доступ к классу, пакету и подклассам (как внутри, так и вне пакета)
Общественные: Доступен для класса, пакета (всех) и подклассов ... Короче говоря, везде.
Public Protected Default и private являются модификаторами доступа.
Они предназначены для инкапсуляции или скрытия и отображения содержимого класса.
Приват недоступен вне класса По умолчанию доступно только в пакете. Защищено как в пакете, так и в любом расширяющем его классе. Публика открыта для всех.
Обычно переменные-члены определены как частные, но методы-члены являются общедоступными.
Default не является модификатором доступа, а два других написаны с ошибками.Модификаторы доступа предназначены для ограничения доступа на нескольких уровнях.
Публичный: Это в основном так же просто, как вы можете получить доступ из любого класса, независимо от того, находится он в том же пакете или нет.
Чтобы получить доступ, если вы находитесь в одном пакете, вы можете получить доступ напрямую, но если вы находитесь в другом пакете, вы можете создать объект класса.
По умолчанию: Доступен в одном пакете из любого класса пакета.
Для доступа вы можете создать объект класса. Но вы не можете получить доступ к этой переменной вне пакета.
Защищено: вы можете получить доступ к переменным в том же пакете, а также к подклассу в любом другом пакете. так что в основном это поведение по умолчанию + Унаследовано.
Чтобы получить доступ к защищенному полю, определенному в базовом классе, вы можете создать объект дочернего класса.
Частный: может быть доступ в том же классе.
В нестатических методах вы можете получить доступ напрямую из-за ссылки это (также в конструкторах), но для доступа в статических методах вам необходимо создать объект класса.
Видно на упаковке. По умолчанию. Никаких модификаторов не требуется.
Виден только классу (частный).
Виден миру (общественный).
Виден пакету и всем подклассам (защищенный).
Переменные и методы можно объявлять без каких-либо вызываемых модификаторов. Примеры по умолчанию:
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(){
}
}
общественный - доступен из любой точки приложения.
дефолт - доступно из пакета.
защищенный - доступен из пакета и подклассов в другом пакете. также
частный - доступен только из своего класса.
Вот лучшая версия таблицы, которая также включает столбец для модулей.
Член частный (i) - это Только, доступный в том же классе, в котором он объявлен.
Член с нет модификатора доступа (j) доступен только внутри классов в том же пакете.
Член защищенный (k) доступен во всех классах одного пакета и в подклассах других пакетов.
Член общественный (l) доступен для всех классов (если только он не находится в модуль, который не экспортирует пакет, в котором он объявлен).
Модификаторы доступа - это инструмент, который поможет вам предотвратить случайное нарушение инкапсуляции (*). Спросите себя, хотите ли вы, чтобы этот член был чем-то внутренним по отношению к классу, пакету, иерархии классов или вообще не внутренним, и выберите соответствующий уровень доступа.
Примеры:
long internalCounter, вероятно, должно быть закрытым, поскольку оно изменяемое и является деталью реализации.void beforeRender(), вызываемый непосредственно перед рендерингом и используемый как перехватчик в подклассах, должен быть защищен.void saveGame(File dst), который вызывается из кода графического интерфейса пользователя, должен быть общедоступным.(*) What is Encapsulation exactly?
Сразу скажу: есть много людей, у которых проблемы с различением красного / зеленого цветов. Таблицы, использующие схемы раскраски красный / зеленый (или желтый / оранжевый / ...) редко бывают "лучше" в чем-либо ;-)
@GhostCat, я не согласен. Я думаю, что красный / зеленый интуитивно сочетается с «работает» / «не работает» для многих людей, т.е. это является лучше, чем многие альтернативы.
@GhostCat Хорошо ... это большая часть населения, чем я ожидал. Я загрузил изображение в этот симулятор дальтонизма и протестировал все разные режимы. Даже в режиме монохромности / ахроматопсии разница в цвете разумная. Вы видите разницу или симулятор выключен? (Я по-прежнему считаю, что красный / зеленый очень интуитивно понятен для людей, видящих цвета.)
Я вижу разницу, но я также могу пройти половину тестов на дальтонизм, которые мы должны сделать в Германии для получения водительских прав ;-) ... но я думаю, что такой симулятор «достаточно хорош».
Я запуталась с цветами
Важно помнить, что эти модификаторы доступа применяются к классу, а не к объекту. Таким образом, objectA типа Chicken может получить доступ к частным свойствам objectB также типа Chicken, но только если код написан внутри класса Chicken.
Модификаторы доступа в 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();
}
}
Output: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();
}
}
Output: Hello
Примечание: Это просто добавка принятого ответа.
Это связано с Java Модификаторы доступа.
A Java access modifier specifies which classes can access a given class and its fields, constructors and methods. Access modifiers can be specified separately for a class, its constructors, fields and methods. Java access modifiers are also sometimes referred to in daily speech as Java access specifiers, but the correct name is Java access modifiers. Classes, fields, constructors and methods can have one of four different Java access modifiers:
- List item
- private
- default (package)
- protected
- public
Из руководств Управление доступом к членам класса:
Access level modifiers determine whether other classes can use a particular field or invoke a particular method. There are two levels of access control:
- At the top level—public, or package-private (no explicit modifier).
- At the member level—public, private, protected, or package-private (no explicit modifier).
A class may be declared with the modifier public, in which case that class is visible to all classes everywhere. If a class has no modifier (the default, also known as package-private), it is visible only within its own package
The following table shows the access to members permitted by each modifier.
╔═════════════╦═══════╦═════════╦══════════╦═══════╗ ║ 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 ║ ╚═════════════╩═══════╩═════════╩══════════╩═══════╝The first data column indicates whether the class itself has access to the member defined by the access level. As you can see, a class always has access to its own members. The second column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The third column indicates whether subclasses of the class declared outside this package have access to the member. The fourth column indicates whether all classes have access to the member.
Access levels affect you in two ways. First, when you use classes that come from another source, such as the classes in the Java platform, access levels determine which members of those classes your own classes can use. Second, when you write a class, you need to decide what access level every member variable and every method in your class should have.
что именно представляет собой дополнение и почему это не редактирование существующего сообщения?
дополнение - Модификаторы доступа. Почему не редактировать? Оставить принятый ответ неизменным по историческим причинам и дать свой ответ.
Часто я осознавал, что запомнить основные концепции любого языка можно, создав аналогии из реального мира. Вот моя аналогия для понимания модификаторов доступа в Java:
Предположим, вы студент университета, и у вас есть друг, который приезжает к вам в гости на выходных. Предположим, что в центре кампуса стоит большая статуя основателя университета.
Когда вы приводите его в университетский городок, первое, что видите вы и ваш друг, - это статуя. Это означает, что любой, кто ходит по кампусу, может смотреть на статую без разрешения университета. Это делает статую ПУБЛИЧНЫЙ.
Затем вы хотите отвести друга к себе в общежитие, но для этого вам необходимо зарегистрировать его как посетителя. Это означает, что он получает пропуск (такой же, как у вас), чтобы попасть в различные здания на территории кампуса. Это сделает его карту доступа ЗАЩИЩЕННЫЙ.
Ваш друг хочет войти в сеть Wi-Fi кампуса, но у него нет для этого учетных данных. Единственный способ, которым он может выйти в Интернет, - это если вы поделитесь с ним своим логином. (Помните, что каждый студент, поступающий в университет, также имеет эти учетные данные). Это сделает ваши учетные данные как БЕЗ МОДИФИКАТОРА.
Наконец, ваш друг хочет прочитать ваш отчет об успеваемости за семестр, который размещен на веб-сайте. Однако у каждого студента есть свой личный логин для доступа к этому разделу веб-сайта кампуса. Это сделает эти учетные данные как ЧАСТНЫЙ.
Надеюсь это поможет!
Когда вы думаете о модификаторах доступа, просто думайте об этом так (применимо как к переменные, так и к методы):
public -> доступен отовсюду
private -> доступен только в том же классе, где он объявлен
Теперь возникает путаница, когда дело касается default и protected.
default -> Ключевое слово модификатора доступа отсутствует. Это означает, что он доступен строго внутри пакета класса. Нигде вне этого пакета к нему можно получить доступ.
protected -> Чуть менее строгий, чем default, и, помимо тех же классов пакетов, к нему могут обращаться подклассы за пределами объявленного упаковка.
Все дело в инкапсуляция (или, как сказал Джо Филлипс, наименьшее знание).
Начните с наиболее ограничительных (закрытых) и посмотрите, не понадобятся ли вам позже менее ограничительные модификаторы.
Мы все используем модификаторы методов и членов, такие как private, public, ... но очень немногие разработчики делают одну вещь - логически используют пакеты для кода организовать.
Например: Вы можете поместить чувствительные методы безопасности в пакет «безопасности». Затем поместите открытый класс, который обращается к некоторому коду, связанному с безопасностью, в этом пакете, но сохраните другие классы безопасности пакет частный. Таким образом, другие разработчики смогут использовать общедоступный класс только извне этого пакета (если они не изменят модификатор). Это не функция безопасности, но будет использование гид.
Outside world -> Package (SecurityEntryClass ---> Package private classes)
Другое дело, что классы, которые сильно зависят друг от друга, могут оказаться в одном пакете и в конечном итоге могут быть подвергнуты рефакторингу или объединению, если зависимость слишком сильна.
Если, наоборот, вы установите все как общественный, будет непонятно, к чему следует или не следует обращаться, что может привести к написанию большого количества javadoc (который ничего не требует через компилятор ...).
общественный
Если член класса объявлен с помощью public, то к нему можно получить доступ из любого места.
защищенный
Если член класса объявлен с защищенным ключевым словом, то к нему можно получить доступ из тех же членов класса, вне членов класса в том же пакете и унаследованных членов класса. Если член класса защищен, то к нему НЕЛЬЗЯ получить доступ из внешнего класса пакета, если внешний упакованный класс не унаследован, т.е. расширяет другой суперкласс пакета. Но член защищенного класса всегда доступен для одних и тех же классов пакетов, НЕ имеет значения, унаследован ли тот же класс пакета или НЕ
дефолт
В Java по умолчанию НЕ используется ключевое слово модификатора доступа. Если член класса объявлен без ключевого слова модификатора доступа, то в этом случае он считается членом по умолчанию. Член класса по умолчанию всегда доступен для тех же членов класса пакета. Но внешний член класса пакета НЕ может получить доступ к членам класса по умолчанию, даже если внешние классы являются подклассами, в отличие от защищенных членов.
частный
Если член класса объявлен с защищенным ключевым словом, то в этом случае он доступен ТОЛЬКО для тех же членов класса.
Следующая блок-схема объясняет, как элементы данных базовый класс являются унаследованный, когда режим доступа производный класс - частный.
Примечание. Объявление членов данных со спецификатором частного доступа известно как сокрытие данных..
Источник: Спецификаторы доступа - частные, общедоступные и защищенные
Речь шла о Java, а не о C++.
@Benoit Но то, что я опубликовал, особенно изображения, не одинаковы для обоих: java и C++? Эти правила не применяются и для java? Благодарность
В C++ модификаторов всего 3, а в java - 4.
аналогия хороша, но спецификатор доступа по умолчанию отсутствует,
OP задал вопрос: «В чем разница между общедоступным, защищенным, частным пакетом и частным в Java?»
Мои два цента :)
частный:
класс -> класс верхнего уровня не может быть частным. внутренние классы могут быть частными, доступными из того же класса.
переменная экземпляра -> доступен только в классе. Нет доступа вне класса.
частный пакет:
класс -> класс верхнего уровня может быть частным для пакета. Он может быть доступен только из того же пакета. Не из дополнительного пакета, не из внешнего пакета.
переменная экземпляра -> доступен из того же пакета. Не из дополнительного пакета, не из внешнего пакета.
защищено:
класс -> класс верхнего уровня не может быть защищен.
переменная экземпляра -> Доступно только в том же пакете или подпакете. Доступ к нему возможен только вне пакета при расширении класса.
общественность:
класс -> доступен из пакета / подпакета / другого пакета
переменная экземпляра -> доступен из пакета / подпакета / другого пакета
Вот подробный ответ
https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md
Доступ к Java изменяет то, что вы можете использовать
Модификатор доступа может применяться для class, field[About], method. Попробуйте получить доступ, создать подкласс или переопределить это.
field или method осуществляется через class.class (подкласса) может быть Любые.method (переопределить) должен быть такой же или расширить егоКласс верхнего уровня (область первого уровня) может быть public и default. Nested class[About] может иметь любой из них
package не претендует на иерархию пакетов
Спецификаторы доступа в Java: В java есть 4 спецификатора доступа: private, package-private (по умолчанию), protected и public в порядке возрастания доступа.
Частный: Когда вы разрабатываете какой-либо класс и хотите, чтобы член этого класса не отображался за пределами этого класса, вы должны объявить его закрытым. к закрытым членам можно получить доступ только в том классе, в котором они определены, то есть охватывающем классе. Доступ к закрытым членам можно получить по ссылке «this», а также по другим экземплярам класса, включающего эти члены, но только в пределах определения этого класса.
Частный пакет (по умолчанию): Этот спецификатор доступа будет предоставлять доступ, указанный спецификатором частного доступа, в дополнение к доступу, описанному ниже.
Когда вы разрабатываете какой-либо пакет и, следовательно, какой-то класс (скажем, Class1) в нем, вы можете использовать спецификатор доступа по умолчанию (не нужно упоминать явно), чтобы предоставить член внутри класса другим классам в вашем (том же) пакете. В этих других классах (в том же пакете) вы можете получить доступ к этим членам по умолчанию в экземпляре Class1. Также вы можете получить доступ к этим элементам по умолчанию в подклассах Class1, скажем Class2 (по этой ссылке, или в экземпляре Class1, или в экземпляре Class2).
По сути, в одном пакете вы можете получить доступ к членам по умолчанию в экземпляре класса напрямую или по ссылке «this» в подклассах.
защищенный: Этот спецификатор доступа будет предоставлять доступ, указанный спецификатором доступа частного пакета, в дополнение к доступу, описанному ниже.
Когда вы разрабатываете какой-либо пакет и, следовательно, некоторый класс (скажем, Class1) в нем, вы должны использовать защищенный спецификатор доступа для члена данных в Class1, если вы не хотите, чтобы этот член был доступен вне вашего пакета (скажем, в пакете потребителя из ваш пакет, то есть клиент, который использует ваши API) в целом, но вы хотите сделать исключение и разрешить доступ к этому члену только в том случае, если клиент пишет класс, скажем, Class2, который расширяет Class1. Таким образом, в общем случае защищенные члены будут доступны по ссылке this в производных классах, то есть в Class2, а также в явных экземплярах Class2.
Пожалуйста, обрати внимание:
Итог: К защищенным членам можно получить доступ в других пакетах, только если некоторый класс из этого другого пакета расширяет класс, включающий этот защищенный член, а защищенный член доступен по ссылке «this» или явным экземплярам расширенного класса в пределах определения расширенного класса.
общественный: Этот спецификатор доступа будет предоставлять доступ, указанный спецификатором защищенного доступа, в дополнение к доступу, описанному ниже.
Когда вы разрабатываете какой-то пакет и, следовательно, какой-то класс (скажем, Class1) в нем, вы должны использовать спецификатор публичного доступа для члена данных в Class1, если вы хотите, чтобы этот член был доступен в других пакетах на экземпляре Class1, созданном в каком-то классе другого упаковка. В основном этот спецификатор доступа следует использовать, когда вы намереваетесь предоставить миру свой член данных без каких-либо условий.
Это изображение поможет вам легко понять основные различия между модификаторами доступа public, private, protected и default. Модификатор по умолчанию применяется автоматически, если вы не объявляете в своем коде модификаторы доступа ant.
Для большей наглядности no modifier == package private | package protected
Это хорошая демонстрация
privateскрывается от других классов внутри пакета.publicпредоставляет классы вне пакета.protected- это версияpublic, ограниченная только подклассами.