10

在jar文件中隐藏某些类真的不可能吗?

我不想让类的直接实例化以保持它更灵活。只有工厂(或立面)才能看到这个罐子。

除了创建两个项目之外,还有其他方法可以解决这个问题吗?(两个项目:第一个包含类(实现),另一个引用第一个并包含工厂;稍后将仅引用第二个)

4

8 回答 8

5

我了解您并不想隐藏实际的类,只是防止它们在工厂类之外构建。我认为通过在类构造函数中使用包私有(默认)可见性可以很容易地实现这一点。唯一的限制是您需要将类和工厂放在同一个包中,因此在大中型代码库中,事情可能会变得不必要地复杂。

于 2011-01-21T14:19:30.557 回答
4

如果我正确理解您的问题,您想确保您的库的用户被迫使用您的工厂来实例化他们的对象,而不是使用构造函数本身。

正如我所看到的,有两种可能性,一种很愚蠢,但在少数特定情况下可用,另一种是最实用且可能最常用的方法。

  1. 您可以将所有类变成 工厂的私有内部类。如果您每个班级有一个工厂,这将起作用,但如果您通过一个工厂管理许多不同的班级,则几乎不可行。
  2. 您可以使用protected访问修饰符来限制对类构造函数的访问。这是使用工厂模式时的常见做法
于 2011-01-21T14:19:40.447 回答
3

如果您的公共工厂方法尝试返回“隐藏”的内容,我认为您将遇到编译器失败或警告。

ClassLoader不,如果不重新实现您自己的或使用 OSGi 或类似的东西,您就无法隐藏公共类。

您可以做的是将接口 api 从实现中分离出来,例如,有一个只包含接口的项目和另一个包含实现的项目。但是,您仍然无法隐藏实现类。

于 2011-01-21T14:20:44.247 回答
2

混淆可以以某种方式帮助您。

于 2011-01-21T14:07:33.363 回答
2

使用标准类加载器和普通的旧 jar 文件,这是不可能的。OSGi 有这样一个概念,即仅使某些包对另一个包可见(即公共 api 和内部实现的分离)。

如果您使用的是 eclipse,则可以使用此命令强制执行此类规则

于 2011-01-21T14:09:39.360 回答
1

如果当您说“不允许直接实例化类以使其更灵活”时我理解正确,则正确执行的外观模式将处理此问题。

将要隐藏的所有类的构造函数限制在包范围内。将外观类打开到公共范围。

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

“如果你的类中有一个变量或方法,你不希望你的类的客户直接访问,不要给它一个公共的、受保护的或私有的声明。由于 Java 设计的疏忽,你可以” t 显式声明默认的“包”可访问性。包的其他成员将能够看到它,但从您的包继承的包外的类不会。受保护的可访问性属性提供了更多的可见性。受保护的方法是可见的继承类,甚至不是同一个包的一部分。包范围(默认)方法不是。这是受保护和包范围之间的唯一区别。“

于 2011-01-21T14:19:49.560 回答
1

您的问题有两种解决方案,它们不涉及将所有类保存在同一个包中。

第一种是使用(Practical API Design, Tulach 2008) 中描述的 Friend Accessor/ Friend Package模式。

二是使用OSGi。这里有一篇文章解释了 OSGi 是如何做到这一点的。

相关问题:1234

于 2011-05-27T15:41:55.697 回答
0

您可以使用自定义类加载器来做这样的魔术,但是:

  • 正确的分隔将仅在配备您的类加载器的项目中可用;
  • 创建这样的加载器的努力是否值得真的值得怀疑。

在这种情况下,我会做一些类似于我们在标准 Java 中看到的事情。例如,您看到javax.xml.stream.XMLInputFactory但在某处您有com.sun.xml.internal.stream.XMLInputFactoryImpl。如果你写它是完全可编译的:

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

尽管您几乎不会这样做 :-) 使用系统属性,您可以控制正在加载的实际实现。对我来说,这种方法在许多情况下都很好。

我希望我正确理解了你的问题;)

干杯!

于 2011-01-21T14:19:55.473 回答