Я не был в ситуации, когда ошибка компилятора, вызванная этими ключевыми словами, спасла бы меня от ошибки.
Это не столько спасает авторов приложений от ошибок, сколько позволяет авторам библиотеки решать, какие части своей реализации они поддерживают.
Если у меня есть библиотека
class C {
public void foo() { ... }
private void fooHelper() { /* lots of complex code */ }
}
Я могу хотеть иметь возможность заменить foo
реализацию и, возможно, fooHelper
радикально измениться . Если группа людей решила использовать fooHelper
несмотря на все предупреждения в моей документации, то я не смогу сделать это.
private
позволяет авторам библиотеки разбивать библиотеки на методы управляемых размеров (и private
вспомогательные классы), не опасаясь, что они будут вынуждены хранить эти внутренние детали в течение многих лет.
Что могло бы стоить компилятору применять скрытие информации?
Напомним, что в Java private
не применяется компилятор, а проверяется байт-код Java .
Может ли рефлексия перекрыть этот механизм? Что могло бы стоить компилятору применять скрытие информации?
В Java не только отражение может переопределить этот механизм. Есть два вида private
в Java. Это private
предотвращает доступ одного внешнего класса к private
членам другого внешнего класса, который проверяется верификатором байт-кода, но также private
и к тем, которые используются внутренним классом через метод синтетического метода доступа с закрытым пакетом, как в
public class C {
private int i = 42;
public class B {
public void incr() { ++i; }
}
}
Поскольку класс B
(действительно именованный C$B
) использует i
, компилятор создает синтетический метод B
доступа, который позволяет получить доступ C.i
таким образом, чтобы он прошел проверку байт-кода. К сожалению, поскольку ClassLoader
позволяет вам создать класс из a byte[]
, довольно просто получить доступ к частным лицам, которые C
открылись для внутренних классов, создав новый класс в C
пакете внутри , что возможно, если C
jar не был запечатан.
Правильное private
применение требует координации между загрузчиками классов, верификатором байт-кода и политикой безопасности, которая может препятствовать отражающему доступу рядовых лиц.
Может ли оно быть использовано для защиты секретного состояния класса от нападения?
Да. «Безопасная декомпозиция» возможна, когда программисты могут сотрудничать, сохраняя при этом свойства безопасности своих модулей - мне не нужно доверять автору другого модуля кода, чтобы не нарушать свойства безопасности моего модуля.
Языки возможностей объектов, такие как Joe-E, используют скрытие информации и другие средства, чтобы сделать возможной безопасную декомпозицию:
Joe-E - это подмножество языка программирования Java, разработанное для поддержки безопасного программирования в соответствии с дисциплиной объектных возможностей. Joe-E предназначен для облегчения построения защищенных систем, а также для облегчения анализа безопасности систем, построенных в Joe-E.
Ссылка на эту страницу дает пример того, как private
правоприменение делает возможной безопасную декомпозицию.
Обеспечение безопасной инкапсуляции.
Рисунок 1. Средство регистрации только для добавления.
public final class Log {
private final StringBuilder content;
public Log() {
content = new StringBuilder();
}
public void write(String s) {
content.append(s);
}
}
Рассмотрим рис. 1, который иллюстрирует, как можно создать средство регистрации только для добавления. При условии, что остальная часть программы написана на Joe-E, рецензент кода может быть уверен, что записи журнала могут быть только добавлены, но не могут быть изменены или удалены. Этот обзор является практичным, поскольку он требует только проверки Log
класса и не требует проверки какого-либо другого кода. Следовательно, проверка этого свойства требует только локальных рассуждений о коде регистрации.