Как разделить личные данные пакета между двумя пакетами в Java?
У меня есть 2 пакета Java, A & B. Предположим, что некоторые классы в пакете B хотят использовать некоторые классы в пакете A, однако, когда разработчик приходит и разрабатывает пакет C (или, скажем, приложение C), он / она будет используйте мой пакет B, но я не хочу, чтобы он / она мог использовать классы в A, которые использует B. То есть я хочу, чтобы мои классы в пакете А были частными, чтобы они были скрыты от разработчика приложения. Однако я хочу, чтобы мой собственный пакет B имел доступ к тем классам, которые являются частными. Можно ли это сделать на Java? Нужно ли мне просто кусать пули и делать классы общедоступными и надеяться, что пользователь не попытается их использовать? Или мне нужно повторить классы, которые находятся в A внутри B?
Я предпочитаю что-то не хакерское (то есть я не хочу использовать рефлексию). Помогите?
2 ответа
Вы можете сделать это с JDK 8 и его Project Jigsaw. Возможно, вы захотите взглянуть на Руководство по быстрому старту Jigsaw.
К сожалению, Jigsaw является частью JDK8, и он еще не полностью готов. Ожидается, что он будет завершен до января 2013 года и не будет выпущен до середины 2013 года.
Однако вы уже можете скомпилировать свои классы с помощью предварительного просмотра JDK 8 и воплотить свои идеи в жизнь.
В этом случае вашу проблему можно решить, разделив ваше приложение на независимые модули. Вы могли бы сделать что-то вроде:
module foo {
exports foo;
permits bar;
permits baz;
}
Здесь модуль foo может потребоваться только модулям с именем bar или baz. Зависимость от модуля другого имени от foo не будет разрешена во время компиляции, установки или выполнения. Если нет положений о разрешениях, то таких ограничений нет.
Не уверен, что альтернативные платформы, такие как OSGI, реализации которых вы можете найти в Apache Felix и Eclipse Equinox, предлагают какую-то функциональность для реализации этих уровней инкапсуляции. Вероятно, вы захотите немного изучить это.
Проблема с OSGi без Jigsaw заключается в том, что любые правила, применяемые средой, могут быть нарушены отражением, когда Jigsaw будет готов для публичного использования, хотя эти правила будут применяться самой Java, как вы читали выше, во время компиляции., время выполнения и время установки.
Вы можете сделать это с OSGi. Android и JDK 6 в качестве цели не являются проблемой в этом случае, есть платформы OSGi, работающие на Android -> например, см. MBedded Server for Android. Вы можете скачать бесплатную некоммерческую версию по ссылке.
У вас есть несколько вариантов, как это сделать в OSGi, в зависимости от того, чего вы хотите достичь.
Вариант 1 (рекомендуется): вы можете поместить пакеты A и B в один и тот же пакет AB и экспортировать только пакет B в манифест этого пакета с помощью Export-Package. Пакет / приложение C или любое другое "пользовательское" приложение может импортировать пакет B и использовать его. И он не может использовать и даже не видит пакет A, потому что он является внутренним для пакета AB. Вам не нужны никакие специальные объявления или зависимости на уровне Java; это будет работать с ЛЮБОЙ версией Jva, потому что модульность и отдельные пространства пакета являются частью основ OSGi и не зависят от последней версии Java или чего-то другого.
Вариант 2: Если по какой-то причине вы хотите, чтобы пакеты A и B были разделены на разные пакеты, вы можете иметь их так, вы будете экспортировать и импортировать пакеты в манифесте, а затем контролировать, какой пакет имеет право импортировать какой пакет, используя разрешения (см. раздел Разрешения OSGi и Услуги условного разрешения). Однако это сложнее понять.
Вариант 3: Вы также можете поместить пакет A в пакет Fragment и позволить ему присоединиться к пакету, содержащему B. Таким образом, B будет иметь доступ к пакету A, но в то же время вы сможете обновить пакет A отдельно. во время выполнения, если хотите. Поскольку пакеты во фрагментах рассматриваются как частные для пакета хоста (в данном случае хост - это пакет, содержащий пакет B), Пакет C не будет видеть A. Он будет видеть только то, что экспортируется Пакетом B.
Поскольку вы не очень хорошо знакомы с OSGi, я рекомендую запустить вариант 1, а затем при необходимости позже вы можете обновить свой подход до варианта 3, если хотите.
@ Эдвин Далорсо: Это определенно неправда, что правила в OSGi могут быть нарушены отражением. Пакеты имеют отдельные загрузчики классов в OSGi. Вы можете отразить в Bundle C столько же, сколько и в классах A, и единственное, что вы получите, - это исключение ClassNotFound - поверьте, я видел это достаточно много раз;)