Локальное поведение "Module local" в Java 9

Поскольку ядром проекта Jigsaw является Java Module System, было бы неплохо иметь возможность ограничивать доступ к определенным элементам программы (классам, методам и полям) только в пределах определенного модуля.

Это может быть полезно, когда в модуле есть некоторые элементы, которые по существу общедоступны для этого модуля, но не должны быть доступны вне этого модуля.

Итак, я говорю о следующем уровне доступа после "package-local", который можно назвать "module-local".

Однако краткий обзор Jigsaw rules и ранних спецификаций не помог мне понять такую ​​функциональность. Более конкретно эта спецификация Modifier не содержит никаких новых элементов.

То есть любая другая возможность сделать это в будущем Java 9?

Ответ 1

A public (т.е. класс, интерфейс, метод или поле) в неэкспортный пакет, по сути, является "локальным модулем". Это будет доступный для всего остального кода в модуле, но не извне модуль.

Невозможно объявить модуль-локальный элемент в экспортированном пакете. Элемент public экспортируемого пакета доступен извне модуль, пакет-частный элемент по-прежнему является закрытым пакетом, а theres нет режима доступа на уровне элемента между этими двумя режимами. Мы могли бы определить новый такой режим, но мы видели несколько убедительных вариантов использования для него и, кроме того, внедрение модульного контроля доступа в JVM при детализации более тонкие, чем экспортные пакеты, будут налагать значительную производительность затраты.

Ответ 2

Короткий ответ

Это может быть полезно, когда в модуле есть некоторые элементы, которые по существу общедоступны для этого модуля, но не должны быть доступны вне этого модуля.

Это невозможно. (Только с помощью модульной системы - существует обходное решение.)

Длинный ответ

Объяснение лежит в термине Accessibility:

Компилятор Java и виртуальная машина рассматривают публичные типы в пакете в одном модуле для доступа к коду в каком-либо другом модуле только тогда, когда первый модуль читается вторым модулем в указанном выше смысле, а первый модуль экспортирует этот пакет. [...]

Тип, на который ссылаются границы модулей, которые недоступны таким образом, непригоден для использования таким же образом, что частный метод или поле непригодны: любая попытка его использования может вызвать сообщение об ошибке компилятором или IllegalAccessError, которые будут выбрасываться виртуальной машиной Java, или IllegalAccessException, которые будут выбраны отражающими API времени выполнения. [...]

Метод или поле, на которое ссылаются границы модулей, доступно, если его доступный тип доступен в этом смысле, и если декларация самого элемента также разрешает доступ.

В то время как существуют разные способы, как и для кого пакет может быть экспортирован, как только компилятор /JVM сочтет тип доступным , не применяется дополнительный механизм. Его члены так же доступны, как и до Jigsaw.

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

Обход

То есть любая другая возможность сделать это в будущем Java 9?

Да.:)

В экспортированном пакете вы можете иметь открытый интерфейс Global, который определяет методы, которые вы хотите экспортировать в мир. Затем используйте либо интерфейс, либо класс Local extend Global, и добавьте все необходимые вам элементы. Ключ в том, что Local не должен находиться в экспортированном пакете!

Теперь, если ваш API модуля возвращает только Global -s, но никогда не принимает их как аргумент метода, вам хорошо идти. Просто убедитесь, что внутренне вы всегда используете - и, возможно, бросаете на - Local.

Если вы также принимаете Global -s, вы должны четко документировать, что это могут быть только случаи, возвращаемые вашим API (т.е. пользователю не разрешено создавать собственную реализацию). Это может показаться непозволительным, но если вы серьезно подумаете о своем первоначальном запросе, он будет иметь те же характеристики.