Скрытие классов в jar-файле - PullRequest
8 голосов
/ 21 января 2011

Действительно ли невозможно скрыть некоторые классы в файле jar?

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

Есть ли другой способ, кроме как решить эту проблему, кроме создания двух проектов? (Два проекта: первый содержит классы (реализацию), а другой ссылается на первый и содержит фабрику; позже будет ссылаться только на второй)

Ответы [ 8 ]

5 голосов
/ 21 января 2011

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

3 голосов
/ 21 января 2011

Я думаю, что у вас будет либо сбой компилятора, либо предупреждение, если ваш общедоступный метод фабрики попытается вернуть что-то "скрытое".

Нет, вы не можете скрыть публичный класс, не переопределив собственный ClassLoader, не используя OSGi или что-то подобное.

Что вы можете сделать, это отделить интерфейс API от реализации, например, есть один проект, который содержит только интерфейсы, и другой объект, который содержит имплементации. Однако вы все еще не можете скрыть классы реализации.

3 голосов
/ 21 января 2011

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

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

  1. Вы можете превратить все свои классы в частные внутренние классы фабрики.Это сработало бы, если у вас была одна фабрика на класс, но вряд ли работоспособно, если у вас много разных классов, управляемых через одну фабрику.
  2. Вы можете использовать модификатор доступа protected, чтобы ограничить доступ к вашим конструкторам классов. Это обычная практика при использовании фабричного шаблона .
2 голосов
/ 21 января 2011

Со стандартными загрузчиками классов обычные старые файлы jar это невозможно. OSGi использует эту концепцию, чтобы сделать видимым для другого пакета только некоторые пакеты, а не другие (то есть разделение публичного API и внутренней реализации).

Если вы используете затмение, вы можете применять такие правила с помощью this

2 голосов
/ 21 января 2011

Запутывание может помочь вам как-то .

1 голос
/ 27 мая 2011

Есть два решения для вашего вопроса, которые не включают хранение всех классов в одном пакете.

Первый - использовать шаблон Friend Accessor / Friend Package , описанный в (Practical API Design, Tulach 2008).

Второй - использовать OSGi.Есть статья здесь , объясняющая, как OSGi выполняет это.

Смежные вопросы: 1 , 2 , 3 и 4 .

1 голос
/ 21 января 2011

Если я правильно вас понимаю, когда вы говорите «не разрешать прямую реализацию классов для обеспечения большей гибкости», правильно выполненный шаблон фасада будет справляться с этим.

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

http://mindprod.com/jgloss/packagescope.html

"Если в вашем классе есть переменная или метод, к которым вы не хотите, чтобы клиенты вашего класса имели прямой доступ, не открывайте его,защищенное или частное объявление. Из-за недосмотра в дизайне Java вы не можете явно объявить доступность «пакета» по умолчанию. Другие члены пакета смогут видеть его, но классы вне пакета, которые наследуются от вашего,не будет. Атрибут защищенной доступности предлагает немного больше видимости. Защищенный метод видим для наследования классов, даже не являющихся частью одного и того же пакета. Метод области видимости пакета (по умолчанию) - нет. Это единственное отличие между защищенной и областью пакета. "

0 голосов
/ 21 января 2011

Вы можете создавать магию с помощью загрузчика пользовательских классов, но:

  • правильное разделение будет доступно только в проекте, в котором работает ваш загрузчик классов;
  • действительно сомнительно, что усилия по созданию такого загрузчика заслуживают внимания.

В таких ситуациях я делал бы нечто похожее на то, что мы можем видеть в стандартной Java. Например, вы видите javax.xml.stream.XMLInputFactory, но где-то у вас есть com.sun.xml.internal.stream.XMLInputFactoryImpl. Это прекрасно компилируется, если вы напишите:

new com.sun.xml.internal.stream.XMLInputFactoryImpl()

хотя вы вряд ли сделаете это :-) С помощью системного свойства вы можете контролировать фактическую загружаемую реализацию. Для меня такой подход хорош во многих ситуациях.

Надеюсь, я правильно понял ваш вопрос;)

Ура!

...