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

108

Я только начал читать книгу о Java и задумался; какой спецификатор доступа используется по умолчанию, если он не указан?

Беннедич
источник
Правильный термин - «модификатор доступа». Слово «спецификатор» не появляется в JLS.
Маркиз Лорн,

Ответы:

116

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

Как указала mdma, это неверно для членов интерфейса, для которых по умолчанию установлено значение «public».

См . Спецификаторы доступа Java

KeatsPeeks
источник
25
неверно - неверно для членов интерфейса. тогда доступ по умолчанию будет публичным
mdma
2
На самом деле это известно как «частный пакет». Сторонние веб-сайты не являются нормативными ссылками. Вы должны цитировать только JLS.
Маркиз Лорн,
81

Спецификатор по умолчанию зависит от контекста.

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

class MyClass   // package private
{
   int field;    // package private field

   void calc() {  // package private method

   }
}

Для членов интерфейса (полей и методов) доступ по умолчанию является открытым. Но обратите внимание, что само объявление интерфейса по умолчанию имеет значение package private.

interface MyInterface  // package private
{
   int field1;         // static final public

   void method1();     // public abstract
}

Если у нас есть декларация

public interface MyInterface2 extends MyInterface
{

}

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

МДМА
источник
1
«Частный пакет» (иногда пишется в исходном коде как /* pp */) - всего лишь удобное имя для доступа по умолчанию . Это не имя JLS.
Том Хотин - tackline
10
@Tom - это правильно, JLS использует «доступ по умолчанию». Я мог бы написать «по умолчанию - доступ по умолчанию». Но это не показалось мне слишком полезным!
mdma
16

Если спецификатор доступа не указан, это доступ на уровне пакета (для этого нет явного спецификатора) для классов и членов классов. Методы интерфейса неявно открыты.

Майкл Боргвардт
источник
9

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

Интересное замечание заключается в том, что protected не ограничивает видимость подклассами, но также и другими классами в том же пакете.

Йоханнес Вахтер
источник
8

Это зависит от того, что это за штука.

  • Типы верхнего уровня (то есть классы, перечисления, интерфейсы и типы аннотаций, не объявленные внутри другого типа) по умолчанию являются частными для пакета . ( JLS §6.6.1 )

  • В классах все члены (что означает поля, методы и объявления вложенных типов) и конструкторы по умолчанию являются частными для пакета . ( JLS §6.6.1 )

    • Когда класс не имеет явно объявленного конструктора, компилятор вставляет конструктор с нулевым аргументом по умолчанию, который имеет тот же спецификатор доступа, что и класс . ( JLS §8.8.9 ) Конструктор по умолчанию обычно неверно указывается как всегда открытый, но в редких случаях это не эквивалентно.
  • В перечислениях конструкторы по умолчанию являются закрытыми . Действительно, конструкторы enum должны быть частными, и указывать их как общедоступные или защищенные - ошибка. Константы перечисления всегда общедоступны и не разрешают никаких спецификаторов доступа. Другие члены перечислений по умолчанию являются закрытыми для пакета . ( JLS §8.9 )

  • В интерфейсах и типах аннотаций все члены (опять же, это означает поля, методы и объявления вложенных типов) по умолчанию являются общедоступными . Действительно, члены интерфейсов и типы аннотаций должны быть общедоступными, и указывать их как частные или защищенные - ошибка. ( JLS §9.3–9.5 )

  • Локальные классы - это именованные классы, объявленные внутри метода, конструктора или блока инициализатора. Они ограничены блоком {.., }в котором они объявлены, и не допускают никаких спецификаторов доступа. ( JLS §14.3 ) Используя отражение, вы можете создавать экземпляры локальных классов из другого места, и они являются частными для пакета , хотя я не уверен, есть ли эта деталь в JLS.

  • Анонимные классы - это созданные пользователем классы, newкоторые определяют тело класса непосредственно в выражении. ( JLS §15.9.5 ) Их синтаксис не разрешает никаких спецификаторов доступа. Используя отражение, вы можете создавать экземпляры анонимных классов из других источников, и они, и их сгенерированные конструкторы являются частными для пакета , хотя я не уверен, есть ли эта деталь в JLS.

  • Блоки экземпляра и статического инициализатора не имеют спецификаторов доступа на уровне языка ( JLS §8.6 и 8.7 ), но блоки статического инициализатора реализованы как метод с именем <clinit>( JVMS §2.9 ), поэтому метод должен внутренне иметь некоторый спецификатор доступа. Я изучил классы, скомпилированные javac и компилятором Eclipse с использованием шестнадцатеричного редактора, и обнаружил, что оба генерируют метод как частный для пакета . Тем не менее, вы не можете позвонить <clinit>()в языке , потому что <и >символы являются недопустимыми в имени метода, а также методы отражения являются жестко отрицать ее существование, поэтому эффективно его спецификатор доступа не является отсутствие доступа . Метод может быть вызван только виртуальной машиной во время инициализации класса.Блоки инициализатора экземпляра не компилируются как отдельные методы; их код копируется в каждый конструктор, поэтому к ним нельзя получить доступ по отдельности, даже путем отражения.

Боанн
источник
7

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

  Access Levels
    Modifier    Class   Package Subclass  EveryWhere
    public        Y        Y       Y         Y
    protected     Y        Y       Y         N
    default       Y        Y       N         N
    private       Y        N       N         N

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

public interface Computer {    
    default void Start() {
        throw new UnsupportedOperationException("Error");
    }    
}

Однако он будет работать только с 8-й версией Java.

Официальная документация

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

Амадеу Антунес
источник
3

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

Брайан Агнью
источник
3

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

абхи
источник
3

Вот цитата о видимости на уровне пакетов из интервью с Джеймсом Гослингом, создателем Java:

Билл Веннерс : Java имеет четыре уровня доступа. По умолчанию это пакет. Я всегда задавался вопросом, удобно ли было сделать доступ к пакету по умолчанию, потому что три ключевых слова, о которых люди из C ++ уже знали, были частными, защищенными и общедоступными. Или если у вас была какая-то конкретная причина, по которой вы считали, что доступ к пакету должен быть по умолчанию.

Джеймс Гослинг : Пакет обычно представляет собой набор вещей, которые написаны вместе. В общем, я мог сделать одно из двух. Один из них - заставить вас всегда вводить ключевое слово, которое дает вам домен. Или у меня могло быть значение по умолчанию. И тогда возникает вопрос, что является разумным дефолтом? И я стремлюсь к наименее опасным вещам.

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

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

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

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

http://www.artima.com/intv/gosling2P.html

Виталий Федоренко
источник
2

Обновление использования ключевого слова в Java 8default : как отметили многие другие, видимость по умолчанию (без ключевого слова)

поле будет доступно изнутри того же пакета, которому принадлежит класс.

Не следует путать с новой функцией Java 8 ( методы по умолчанию ), которая позволяет интерфейсу предоставлять реализацию, когда он помечен defaultключевым словом.

См .: Модификаторы доступа

Ахмад Сани
источник
-2

Прежде всего позвольте мне сказать, что в java нет такого термина, как "спецификатор доступа". Мы должны называть все «Модификаторами». Как мы знаем, final, static, synchronized, volatile .... называются модификаторами, даже Public, private, protected, default, abstract также должны называться модификаторами. По умолчанию это такие модификаторы, в которых физическое существование отсутствует, но модификаторы не размещены, тогда их следует рассматривать как модификаторы по умолчанию.

Чтобы обосновать это, возьмем один пример:

public class Simple{  
    public static void main(String args[]){  
     System.out.println("Hello Java");  
    }  
}  

Результат будет: Hello Java

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

Сагар Раут
источник
Первое предложение уместно, но тот факт, что внешний класс не может быть частным, не доказывает, что в Java не существует такой вещи, как спецификатор доступа.
Маркиз Лорн,
@EJP Это просто пример. Я говорю, что термин спецификатор доступа используется в других языках, таких как c, dot net и т. Д., Но технический термин в java для этого - модификаторы. Если вы используете eclipse или любую другую среду IDE, вы можете увидеть, что во время создания нового класса нас просят указать имя модификатора, и в списке они предоставляют общедоступные, частные, абстрактные и т. Д.
Сагар Раут
В моем примере я пытаюсь сказать, что компилятор выдает сообщение об ошибке: закрытые модификаторы не разрешены, он не выдает сообщение, такое как закрытый спецификатор доступа, не разрешен. Итак, технический термин, который мы должны сказать, это модификаторы в java, а не спецификатор доступа в java
Сагар Раут