2011-01-21 74 views
8

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

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

除了创建两个项目之外,还有别的办法解决这个问题吗? (两个项目:第一个包含的类(实现)和第一个另外一个引用,并包含了工厂;后来只有第二个将被引用)

+1

我不确定你的意思是“隐藏”。 Jar文件只是.zip文件,所以任何人都可以打开它们并在里面看到你的类文件。 – jonescb 2011-01-21 14:07:14

+0

我只是想避免这些类可以在外部(偶然)用于实例化。 – nrainer 2011-01-21 14:16:36

+1

我确实认为你应该相信你的课程的用户,并提供足够的文档来说明使用什么以及不应该使用什么。无论如何,你无法防止所有使用你的罐子的开发人员犯的错误。当然,一种选择是让自己的构造函数变得如此复杂,没有人能够理解它们,并且会自然地回退到工厂类中:D – 2011-01-21 14:25:43

回答

3

我认为如果你的公共工厂方法试图返回一些“隐藏”的东西,你会遇到编译器故障或警告。

不,你不能隐藏一个公共课程,而无需重新实现你自己的ClassLoader或使用OSGi或类似的东西。

你可以做的是将接口API与实现分开,有一个只包含接口的项目和另一个包含实现的项目。但是,您仍然无法隐藏实现类。

2

Obfuscation可以帮助你莫名其妙

+0

借调,即使它没有隐藏它。 – 2011-01-21 14:10:40

2

对于标准的类加载器来说,这是不可能的。 OSGi认为这个概念使其他包只能看到一些包,而不是其他包(即公共API和内部实现的分离)。

如果你是usinf日食可能会强制执行这些规则与this

5

我理解你不知道的隐藏实际的课程,只是防止其工厂类以外的工程。我认为这可以通过在类构造函数中使用包私有(默认)可见性很容易实现。唯一的限制是你需要将类和工厂放在同一个包中,所以在中等到更大的代码库中可能会产生不必要的复杂。

3

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

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

  1. 你可以让所有的类到 工厂 private inner classes。如果您每个班级有一个工厂 ,但是如果您有很多 不同的班级通过一个工厂管理 ,则几乎不可能 可行。
  2. 您可以使用protected访问修饰符 限制访问您的类 构造函数。 这是常见的 练习时使用factory pattern
1

如果我在正确理解你说“不允许直接实例化类来保持它更灵活”时,正确执行的外观模式将处理此问题。

限制你想隐藏到包范围的所有类的构造函数。打开外观类到公共范围。

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

“如果你在 类变量或方法,你不希望客户端类直接访问的 , 不给它一个公开,保护或 私人由于 在Java设计中的疏忽,您的 无法明确声明默认的 “包”的可访问性。该包的其他成员 将能够看到它, 但包外的类 继承你的,不会的。 受保护的可访问性属性 提供了稍微更多的可见性。 A 受保护的方法对 继承类是可见的,即使不是 的一部分也是相同的包。包的范围 (默认)方法不是。那就是 保护套和 套件范围之间的唯一区别。 “

0

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

  • 正确的分离只会在你的类加载器配备一个项目可用;
  • 这真的值得怀疑的努力创建这样的加载器是值得的

在这种情况下,我会做类似于我们在标准Java中看到的东西。Egyou请参阅javax.xml.stream.XMLInputFactory但在某处您有com.sun.xml.internal.stream.XMLInputFactoryImpl。这是完全编译的,如果你写:

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

虽然你将很难做到这一点:-)有了一个系统属性,你可以控制被加载的实际执行情况。对我来说,在许多情况下这种方法都很好。

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

干杯!

1

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

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

第二个是使用OSGi。有一篇文章here解释了OSGi如何完成这个。

相关问题:12,34