Подтвердить что ты не робот

Почему я могу иметь публичного участника в непубличном классе?

class MyClass 
{
    public static final int num=90;
}
  • Почему мне разрешено создавать открытый член в непубличном классе?
  • Есть ли другой способ доступа к этому члену, о котором я не знаю (кроме имени класса)?
4b9b3361

Ответ 1

Поскольку ваш вопрос касался участников, я буду рассматривать оба поля и методы (нестатические; Anthony Accioly answer затрагивает другой хороший вариант использования, который также включает в себя статические поля).

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

Развернув ответ Mik378, рассмотрите, например, следующий (надуманный пример):

import ...;

class BleebleAscendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

class BleebleDescendingComparator implements Comparator<Bleeble> {
    @Override public int compare (Bleeble o1, Bleeble o2) { ... }
}

public class BleebleView {  
    public enum SortMode { ASC, DESC };
    public Comparator<Bleeble> getDisplayOrderComparator (SortMode mode) {
        if (mode == SortMode.ASC)
            return new BleebleAscendingComparator();
        else
            return new BleebleDescendingComparator();
    }
}

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

Это же рассуждение относится к внутренним классам, например, private или protected. Если вы не смогли объявить методы public, у вас не было бы способа переопределить методы интерфейсов, которые они наследуют, или классы, которые они расширяют.

Практические примеры:

  • Вы используете это каждый раз, когда вы переопределяете открытый метод в анонимном внутреннем классе (например, каждый раз, когда вы переопределяете public void actionPerformed в анонимном ActionListener).

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

  • Часто переопределенный public toString() является еще одним распространенным примером открытого участника потенциально непубличного класса.

  • Более сложным примером является использование java.sql.Driver в java.sql.DriverManager (в общем случае factory -типы сильно используют эту концепцию) - реализация драйвера SQL может не сделать общедоступными классы реализации (например, драйвер Oracle производит непубличные объекты Connection).

  • Еще много... если вы будете следить за примерами этого, вы будете удивлены, насколько он распространен на самом деле!

Ответ 2

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

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

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

Ответ 3

Не забывайте, что классы с default доступом могут быть подклассифицированы классами public в том же пакете.

package package1;

class MyDefaultClass {

    public static final int MY_CONSTANT = 0xCAFEBABE;
}

public class PublicExporter extends MyDefaultClass {

}

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

package package2;

import package1.PublicExporter;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", PublicExporter.MY_CONSTANT);
    }
}

Потребители могут даже импортировать статические члены:

import static package1.PublicExporter.MY_CONSTANT;

public class Consumer {
    public static void main(String[] args) {
        System.out.printf("%x\n", MY_CONSTANT);
    }
}

Ответ 4

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

Помните, что на Java у вас может быть только 1 открытый класс для единицы компиляции (. java file), и этот открытый класс должен иметь то же имя, что и блок компиляции. Помимо этого, он не "владеет" правом собственности на ключевое слово public.

Тот факт, что вы объявили num как public и static, позволяет вам сказать System.out.println(MyClass.num). Атрибут public позволяет получить переменную num напрямую. Таким образом, вам не нужно создавать метод для возврата num для вас. Поскольку это общедоступно, вы также можете сказать

      MyClass mc = new MyClass();
      System.out.println(mc.num);

Однако, поскольку вы также добавили объявление static, вам нужно получить доступ к нему только через имя класса, то есть MyClass.num

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