Я не был в ситуации, когда ошибка компилятора, вызванная этими ключевыми словами, спасла бы меня от ошибки.
Это не столько спасает авторов приложений от ошибок, сколько позволяет авторам библиотеки решать, какие части своей реализации они поддерживают.
Если у меня есть библиотека
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пакете внутри , что возможно, если Cjar не был запечатан.
Правильное 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
класса и не требует проверки какого-либо другого кода. Следовательно, проверка этого свойства требует только локальных рассуждений о коде регистрации.