如何在Java中的两个包之间共享包私有数据?

时间:2012-06-12 02:30:49

标签: java package share encapsulation package-private

我有2个Java包,A& B.假设包B中的某些类想要使用包A中的某些类,但是,当开发人员出现并开发包C(或者说,应用程序C)时,他/她将使用我的包B但是我不要希望他/她能够使用B正在使用的A中的类。也就是说,我希望包A中的类是包私有的,以便它们对应用程序开发人员是隐藏的。但是,我希望我自己的包B能够访问那些包私有的类。这可以用Java完成吗?我基本上只需要咬紧牙关并公开课程,并希望用户不要尝试使用它们吗?或者,我是否需要复制B内部A中的类?

我的偏好不是hack-y(即我不想使用反射)。帮助

2 个答案:

答案 0 :(得分:6)

您可以使用JDK 8及其Project Jigsaw来完成此操作。您可能想看看Project Jigsaw Quickstart Guide

不幸的是,Jigsaw是JDK8的一部分,它还没有完全准备好。预计功能不完整until January 2013并且不会在2013年年中之前发布。

但是,您已经可以使用JDK 8预览编译您的类,并使您的想法有效。

在这种情况下,您的问题可以通过将应用程序划分为独立模块来解决。你可以这样做:

module foo {
    exports foo;
    permits bar;
    permits baz;
}

这里只有名为bar或baz的模块才需要模块foo。在foo上对某个其他名称的模块的依赖将无法在编译时,安装时间或运行时解析。如果没有许可条款,则没有这样的限制。

不确定OSGI之类的替代框架,您可以在Apache FelixEclipse Equinox中找到实现提供某种功能来实现这些级别的封装。您可能想要对此进行一些调查。

没有Jigsaw存在的OSGi的问题是,无论框架强制执行的规则是否可以通过反射来破解,一旦Jigsaw准备好供公众使用,这些规则将由Java本身强制执行,如你在上面阅读,在编译时,运行时和安装时间。

答案 1 :(得分:2)

您可以使用OSGi执行此操作。 Android和JDK 6作为目标在这种情况下不是问题,在Android上运行OSGi框架 - >例如见mBedded Server for Android。您可以从链接下载免费的非商业版本。

根据您想要实现的目标,您可以在OSGi中有多种选择。

选项1(推荐): 您可以将包A和B放在同一个包AB中,并使用Export-Package仅导出此包清单中的包B. 包/应用程序C或任何其他“用户”应用程序可以导入包B并使用它。并且它不能使用甚至看不到包A,因为它是捆绑AB的内部。您不需要Java级别的任何特殊声明或依赖项;这将适用于任何Jva版本,因为模块化和单独的包空间是OSGi基础的一部分,并且不依赖于最新的Java版本或smth。

选项2: 如果出于某种原因,您希望将包A和B分隔在不同的包中,则可以使用它们,您将导出并导入清单中的包,然后通过使用权限控制哪个包有权导入哪个包(请参阅OSGi)许可和条件许可服务)。但是,实现起来更加复杂。

选项3:您还可以将包A放入Fragment包中,并允许它附加到包含B的包。这样,B将可以访问包A,但同时您将能够更新如果需要,在运行时单独打包A.由于片段中的包被视为主机束的私有(在这种情况下,host是包含包B的包),因此Bundle C将不会看到A.它只会看到Bundle B导出的内容。

由于您不熟悉OSGi,我建议您启动选项1,然后如果需要,您可以根据需要升级选项3的方法。

@Edwin Dalorzo:OSGi中的规则绝对不能通过反思来打破。捆绑包在OSGi中有单独的类加载器。你可以尽可能多地从Bundle C反映出A类,你唯一能得到的就是ClassNotFound异常 - 相信我,我已经看过足够多次了;)