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

3172

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

intrepion
источник
161
privateскрывается от других классов в пакете. publicподвергает классам вне пакета. protectedверсия publicограничена только подклассами.
Museful
87
@Tennenrishin - Нет; В отличие от C ++, в Java protectedэтот метод также доступен из всего пакета. Эта глупость в модели видимости Java нарушает цель protected.
Николас Барбулеско
35
@Nicolas Это доступно из всего пакета, с или без protected. В качестве модификатора доступа все, что protectedнужно сделать, это предоставить подклассам вне пакета.
Музейный
15
@tennenrishin - ну, вот что сказал Николас ... и вы просто повторяете это сейчас. Первоначально вы сказали, что protected- и я цитирую - «версия публичного доступа, ограниченная только подклассами», что не соответствует действительности по вашему собственному допущению, так как защищенный также разрешает доступ через весь пакет (то есть он не ограничивает доступ к подклассам. )
luis.espinal
10
Я также согласен с Николасом в том, что режим защищенного доступа в Java является идиотским. Случилось так, что Java объединила классификаторы ограничения доступа по горизонтали (решетке) и по вертикали. Область действия по умолчанию - ограничение по горизонтали / решетке, причем решетка является пакетом. Публичность - это еще одно горизонтальное ограничение, где решеткой является весь мир. Частные и (C ++) защищенные являются вертикальными. Было бы лучше, если бы у нас был сквозной доступ, скажем, protected-packageдля тех редких случаев, когда он нам действительно нужен, оставляя protectedэквивалент эквивалентной версии C ++ защищенной.
luis.espinal

Ответы:

5639

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

______________________________________________________________
| │ Класс │ Пакет │ Подкласс │ Подкласс │ Мир |
| Same │ │ (тот же pkg) │ (diff pkg) │ |
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| публичный │ + │ + │ + │ + │ + | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| защищенный │ + │ + │ + │ + │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| без модификаторов│ + │ + │ + │ │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| частный │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +: доступно пусто: недоступно
Дэвид Сегондс
источник
5
Приведенная выше таблица неверна, поскольку даже privateчлены могут быть просмотрены / использованы любым классом / статическим методом в одном и том же исходном файле.
Усаги Миямото
5
Доступ к защищенному члену возможен только из подкласса одного и того же пакета, но не из подкласса из другого пакета. В приведенной выше таблице должна быть поправка
Никс
2
Мир в вашем проекте . Я должен объяснить дальше. Библиотеки находятся в вашем проекте, и если вы создаете библиотеку, они также предоставляют эти публичные классы и методы. Так что говорить только в рамках вашего проекта немного не так. «Все, что использует это» - лучшее описание.
adprocas
3
Например, если у меня есть MyClassи я делаю, у AnotherClass extends MyClassменя будет доступ ко всем защищенным и открытым методам и свойствам изнутри AnotherClass. Если я MyClass myClass = new MyClass();в AnotherClassгде - нибудь - скажем , конструктор - я буду иметь доступ только к публичным методам , если он находится в другом пакете. Обратите внимание, что если я это сделаю, = new MyClass() { @Override protected void protectedMethod() { //some logic } };то я получу доступ к защищенным методам, но это то же самое, что и расширение, но вместо этого встроенное.
adprocas
3
К сожалению, этот ответ является грубым упрощением. Реальность немного сложнее, особенно если учесть, protectedчто (на самом деле это довольно сложный модификатор доступа для полного понимания - большинство людей, которые думают, что знают, что на protectedсамом деле означает, не знают ). Кроме того, как отметил Богемян, он не отвечает на вопрос - он ничего не говорит о том, когда использовать каждый модификатор доступа. По моему мнению, этот ответ не достаточно плох, чтобы понизить, но близко. Но более 4000 голосов? Как это случилось?
Дауд ибн Карим
483

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

Частный

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

Пакет Приват

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

защищенный

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

общественного

Каждый может это увидеть.

опубликованный

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

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

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

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

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

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

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

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

Schwern
источник
26
friends -> «Чем меньше вы знаете об этом, тем лучше» ---> Это обеспечивает избирательную видимость, которая по-прежнему превосходит конфиденциальность пакета. В C ++ он имеет свое применение, потому что не все функции могут быть функциями-членами, и друзья лучше, чем публичные публикации. Конечно, существует опасность злоупотребления злыми умами.
Себастьян Мах
30
Следует также отметить, что «защищенный» в C ++ имеет другое значение - защищенный метод является по сути закрытым, но все же может вызываться из наследующего класса. (В отличие от Java, где он может вызываться любым классом в одном и том же пакете.)
Рис ван дер Варден,
9
@RhysvanderWaerden C # - это то же самое, что и C ++ в этом аспекте. Я нахожу довольно странным, что Java не позволяет объявлять члена, который доступен подклассу, но не весь пакет. Это как бы перевернулось - пакет имеет более широкий охват, чем дочерний класс!
Конрад Моравский
15
@KonradMorawski IMHO пакет меньше, чем подкласс. Если вы не объявили свой класс финальным, пользователи должны иметь возможность подкласса его - так что Java-защита является частью вашего опубликованного интерфейса. OTOH, пакеты неявно разрабатываются одной организацией: например, com.mycompany.mypackage. Если ваш код объявляет себя в моем пакете, вы неявно объявляете себя частью моей организации, поэтому мы должны общаться. Таким образом, пакет публикуется для меньшей / легче доступной аудитории (люди в моей компании), чем для подкласса (люди, которые расширяют мой объект) и, таким образом, считается меньшей видимостью.
одноименный
2
friendхорошо для определения особых отношений между классами. Это позволяет превосходную инкапсуляцию во многих случаях при правильном использовании. Например, он может использоваться привилегированным классом фабрики для внедрения внутренних зависимостей в составной тип. У него плохое имя, потому что люди, которые не заботятся о правильном поддержании хорошо спроектированной объектной модели, могут злоупотреблять ею, чтобы облегчить свою рабочую нагрузку.
Деннис
434

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

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

Пояснения

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

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

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

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


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

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

Примеры:

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

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

aioobe
источник
11
Просто скажу: есть много людей, у которых есть проблемы с различением красного / зеленого цвета. Таблицы, использующие красные / зеленые (или желтые / оранжевые / ...) схемы окраски, редко бывают «лучше» в чем-либо ;-)
GhostCat
1
@ GhostCat, я не согласен. Я думаю , что красный / зеленый Выравнивает интуитивно с «работой» / «не работает» для многих людей, т.е. это лучше , чем у многих альтернатив.
августа
8
colourblindawareness.org/colour-blindness/… ... 8% дальтоников можно разделить примерно на 1% дейтеранопов, 1% протанопов, 1% протаномалозных и 5% дейтераномных . И так как я один из тех 50% из этих 5%, будьте уверены: красный / зеленый отстой.
GhostCat
6
@ GhostCat Хорошо ... это большая часть населения, чем я ожидал. Я загрузил изображение в этот симулятор дальтонизма и протестировал все разные режимы. Даже в режиме монохроматичности / ахроматопсии разница в цвете является разумной. Вы видите разницу или симулятор выключен? (Я по-прежнему придерживаюсь мнения, что красный / зеленый очень интуитивно понятен для людей, которые видят цвета.)
aioobe,
3
Я вижу разницу, но я также могу пройти половину тестов на дальтонизм, которые мы должны сделать в Германии для получения водительских прав ;-) ... но я думаю, что такой симулятор "достаточно хорош".
GhostCat
206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________
Abdull
источник
1
Стоит выразить словами: «Защищенный модификатор делает объект доступным для других пакетов, тогда как default / no-modifier ограничивает доступ к одному и тому же пакету»
vanguard69
2
@ vanguard69, protectedмодификатор делает помеченную вещь (класс, метод или поле) доступной для какого-то другого класса в каком-то другом пакете только в том случае, если другой класс является подклассом класса, в котором объявлена ​​эта protectedпомеченная вещь .
Абдул
"nonsubbed"? "этот подкласс в другой упаковке"? Да. Я думал, что знаю Java.
Сехе
@AlexanderFarber вы оптимизировали для конкретной конфигурации браузера? Это мой хром сейчас, а это Firefox
сех
Хм, давайте вернем мои изменения тогда
Александр Фарбер
165

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

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

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

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

Джон Нильссон
источник
3
@RuchirBaronia, "world" = весь код приложения, независимо от того, где он находится.
Андрейс
116

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

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

Резюме

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

  • Member is private: Только если member определен в том же классе, что и вызывающий код.
  • Участник является частным пакетом: только в том случае, если вызывающий код находится в пакете, который непосредственно входит в состав участника.
  • Member is protected: тот же пакет, или если member определен в суперклассе класса, содержащего вызывающий код.
  • Участник public: Да.

К каким спецификаторам доступа применяются

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

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

Все спецификаторы доступа возможны для членов класса (конструкторы, методы и статические функции-члены, вложенные классы).

Связанный: Доступность Класса Java

порядок

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

public> protected> package-private> private

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

Ноты

  • Методы класса могут получить доступ к закрытым членам других объектов того же класса. Точнее, метод класса C может обращаться к закрытым членам C на объектах любого подкласса C. Java не поддерживает ограничение доступа экземпляром, только классом. (Сравните со Scala, который поддерживает его использование private[this].)
  • Вам нужен доступ к конструктору для создания объекта. Таким образом, если все конструкторы являются закрытыми, класс может быть создан только с помощью кода, живущего внутри класса (обычно это статические фабричные методы или инициализаторы статических переменных). Аналогично для частных или защищенных конструкторов.
    • Только наличие частных конструкторов также означает, что класс не может быть разделен на подклассы извне, поскольку Java требует, чтобы конструкторы подкласса неявно или явно вызывали конструктор суперкласса. (Однако он может содержать вложенный класс, который подклассирует его.)

Внутренние классы

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

Тем не менее, это довольно сложно, и для полной информации, обратитесь к Спецификации языка Java . (Да, в прошлом были ошибки компилятора.)

Чтобы почувствовать, как они взаимодействуют, рассмотрим этот пример. Возможно «утечка» частных внутренних классов; обычно это предупреждение:

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

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

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

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

Некоторые связанные вопросы:

Механическая улитка
источник
1
«модификаторы, отличные от public, запрещены» - с Java 9 это уже не так: интерфейсы также могут иметь закрытые методы.
MC Emperor
96

Как правило большого пальца:

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

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

  • (D) irect (вызывается из метода внутри того же класса или через синтаксис this).
  • (R) eference (вызывать метод, используя ссылку на класс или через синтаксис "точка").
  • (I) наследование (через подклассы).

тогда у нас есть эта простая таблица:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+
nxhoaf
источник
54

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

  • public: доступно везде.
  • protected: доступно классам одного пакета и подклассам, находящимся в любом пакете.
  • по умолчанию (модификатор не указан): доступен для классов одного и того же пакета.
  • private: доступно только в одном классе.
Ravi
источник
48

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

  • Предположим, что у нас есть 2 класса; Fatherи Sonкаждый в своем пакете:

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

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

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

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

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. По ссылке, тип которой совпадает с классом:

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

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • Следующие ситуации недопустимы.

    1. Для ссылки, тип которой является родительским классом, и он находится вне пакета, где foo()определен ( fatherpackage):

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

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
Eng.Fouad
источник
Object#clone()это пример protectedчлена.
Eng.Fouad
В чем разница между выполнением super.foo()и первой неверной ситуацией f.foo()?
cst1992
1
@ cst1992 Это сбивает с толку, но смотрите спецификацию языка Java 6.6.2: «Защищенный член или конструктор объекта может быть доступен извне пакета, в котором он объявлен только кодом, отвечающим за реализацию этого объекта». С super.foo () ссылка «super» является «непосредственно ответственной за реализацию», а ссылка «f» - нет. Почему? Потому что вы можете быть на 100% уверены, что «супер» относится к типу «Отец», но не для «f»; во время выполнения это может быть какой-то другой подтип отца. См. Docs.oracle.com/javase/specs/jls/se9/html/…
скомиса
1
Приятно читать ответ от того, кто понимает protected. К сожалению, все остальные ответы на этой странице, которые определяют protectedэто, немного ошибочны.
Дауд ибн Карим
30

Частный

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

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

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

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

Запись

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


защищенный

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

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

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

Запись

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


общественного

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

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

  • Разные пакеты

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

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


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

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

  • В рамках одного пакета

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

Запись

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

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

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

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

Nambi
источник
21

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

Джо Филлипс
источник
20

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

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

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

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

самкит шах
источник
17

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

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

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

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

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

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

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

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

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

Prashant
источник
16

Модификаторы доступа в Java.

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

1. По умолчанию:

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

Например,

// Saved in file A.java
package pack;

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

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

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

Этот доступ более ограничен, чем общедоступный и защищенный, но менее ограничен, чем частный.

2. Публичная

Может быть доступен из любого места. (Глобальный доступ)

Например,

// Saved in file A.java

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

// Saved in file B.java

package mypack;
import pack.*;

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

Вывод: Привет

3. Частный

Доступно только внутри одного класса.

Если вы попытаетесь получить доступ к закрытым членам одного класса в другом, вы получите ошибку компиляции. Например,

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

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

4. Защищенный

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

Например,

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

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

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

Вывод: Привет

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

AFFY
источник
14
  • общедоступный - доступен из любой точки приложения.

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

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

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

Шайлендра Сингх
источник
14

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

Доступно только для класса ( личное ).

Видимый миру ( публичный ).

Доступно для пакета и всех подклассов ( защищено ).

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

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

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

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

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

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

Пример:

public void cal(){

}

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

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

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

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

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}
амила исура
источник
12

Эта страница хорошо описывает модификатор защищенного доступа и доступа по умолчанию

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

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

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

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

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

Дов Вассерман
источник
6

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

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

Из модификаторов доступа Java :

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

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

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

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

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

Класс может быть объявлен с модификатором public, и в этом случае этот класс виден всем классам везде. Если класс не имеет модификатора (по умолчанию, также известного как 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     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

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

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

ישו אוהב אותך
источник
1
Что именно является дополнением, и почему это не редактирование существующего поста?
Сех
Дополнение - Модификаторы доступа. Почему бы не редактировать? Сохранить принятый ответ без изменений для исторической пользы и дать мой ответ.
ישו אוהב אותך
5

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

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

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

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

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

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

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

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

  • Когда вы приводите его в кампус, первое, что вы и ваш друг видите, это эта статуя. Это означает, что любой, кто ходит по кампусу, может посмотреть на статую без разрешения университета. Это делает статую как PUBLIC .

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

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

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

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

Жадный кодер
источник
4

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

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

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

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

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

Притам Банерджи
источник
4

Доступ Java изменяет, который вы можете использовать

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

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

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

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

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

Быстрые модификаторы доступа

yoAlex5
источник
2

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

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

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

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

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

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

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

Кристоф Русси
источник
2

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

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

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

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

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

leonidaa
источник
1
Вопрос был о Java, а не о C ++.
Бенуа
1
@Benoit Но то, что я выложил, изображения в специальных, не одинаковы для обоих: Java и C ++? Эти правила не распространяются и на Java? спасибо
leonidaa
2
В C ++ есть только 3 модификатора, в то время как в java их 4.
Бенуа
1
аналогия хорошая, но спецификатор доступа по умолчанию отсутствует,
мс
1
OP задал вопрос "В чем разница между общедоступным, защищенным, закрытым для пакета и частным в Java?"
JL_SO
2

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

частный:

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

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

пакет-частное:

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

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

защищенный:

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

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

общественности:

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

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

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

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

Mudassar
источник
1
  • общественности

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

  • защищенный

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

  • дефолт

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

  • частный

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

alexvipul
источник
-1

Спецификаторы доступа в Java: в java есть 4 спецификатора доступа: приватный, приватный (по умолчанию), защищенный и публичный в порядке возрастания доступа.

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

Частный пакет (по умолчанию) : этот спецификатор доступа предоставит доступ, указанный спецификатором частного доступа, в дополнение к описанному ниже доступу.

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

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

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

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

Пожалуйста, обратите внимание:

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

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

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

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

Тушар Бавискар
источник