Вопрос: В Java разница между пакетом private, public, protected и private


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


2431


источник


Ответы:


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

| Класс | Пакет | Подкласс | Подкласс | Мир
            | | | (такой же pkg) | (diff pkg) |
------------ + ------- + --------- + ---------- + -------- - + --------
общественные | + | + | + | + | +
------------ + ------- + --------- + ---------- + -------- - + --------
защищенный | + | + | + | + |
------------ + ------- + --------- + ---------- + -------- - + --------
нет модификатора | + | + | + | |
------------ + ------- + --------- + ---------- + -------- - + --------
частные | + | | | |

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

4541



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

Частный

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

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

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

защищенный

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

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

Все это видят.

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

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

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

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

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

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

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

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

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


352



Вот лучшая версия таблицы. (Будущее доказательство с колонкой для модулей.)


Java Access Modifiers

Пояснения

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

  • Член с нет модификатора доступа доступен только в классах в одном пакете.

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

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


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

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

Примеры:

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

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


233



                | 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         |              |     ✘     |       ✘       |   ✘    

162



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

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

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

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


128



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

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

Резюме

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

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

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

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

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

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

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

порядок

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

public> protected> package-private> private

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

Заметки

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

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


93



As a rule of thumb:

  • private: class scope.
  • default (or package-private): package scope.
  • protected: package scope + child (like package, but we can subclass it from different packages). The protected modifier always keeps the "parent-child" relationship.
  • public: everywhere.

As a result, if we divide access right into three rights:

  • (D)irect (invoke from a method inside the same class).
  • (R)eference (invoke a method using a reference to the class, or via "dot" syntax).
  • (I)nheritance (via subclassing).

then we have this simple table:

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

63



In very short

  • public: accessible from everywhere.
  • protected: accessible by the classes of the same package and the subclasses residing in any package.
  • default (no modifier specified): accessible by the classes of the same package.
  • private: accessible within the same class only.

43



The most misunderstood access modifier in Java is protected. We know that it's similar to the default modifier with one exception in which subclasses can see it. But how? Here is an example which hopefully clarifies the confusion:

  • Assume that we have 2 classes; Father and Son, each in its own package:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Let's add a protected method foo() to Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • The method foo() can be called in 4 contexts:

    1. Inside a class that is located in the same package where foo() is defined (fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. Inside a subclass, on the current instance via this or super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. On an reference whose type is the same class:

      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. On an reference whose type is the parent class and it is inside the package where foo() is defined (fatherpackage) [This can be included inside context no. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • The following situations are not valid.

    1. On an reference whose type is the parent class and it is outside the package where foo() is defined (fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. A non-subclass inside a package of a subclass (A subclass inherits the protected members from its parent, and it makes them private to non-subclasses):

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

31



Private

  • Methods,Variables and Constructors

Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself.

  • Class and Interface

Private access modifier is the most restrictive access level. Class and interfaces cannot be private.

Note

Variables that are declared private can be accessed outside the class if public getter methods are present in the class. Variables, methods and constructors which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class.


Protected

  • Class and Interface

The protected access modifier cannot be applied to class and interfaces.

Methods, fields can be declared protected, however methods and fields in a interface cannot be declared protected.

Note

Protected access gives the subclass a chance to use the helper method or variable, while preventing a nonrelated class from trying to use it.


Public

A class, method, constructor, interface etc declared public can be accessed from any other class.

Therefore fields, methods, blocks declared inside a public class can be accessed from any class belonging to the Java Universe.

  • Different Packages

However if the public class we are trying to access is in a different package, then the public class still need to be imported.

Because of class inheritance, all public methods and variables of a class are inherited by its subclasses.


Default -No keyword:

Default access modifier means we do not explicitly declare an access modifier for a class, field, method, etc.

  • Within the same Packages

A variable or method declared without any access control modifier is available to any other class in the same package. The fields in an interface are implicitly public static final and the methods in an interface are by default public.

Note

We cannot Override the Static fields.if you try to override it does not show any error but it doesnot work what we except.

Related Answers

References links

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


24



The difference can be found in the links already provided but which one to use usually comes down to the "Principle of Least Knowledge". Only allow the least visibility that is needed.


15