6

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

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

4

2 回答 2

6

您可以使用JDK 8及其Project Jigsaw来实现。您可能想看看Project Jigsaw 快速入门指南

不幸的是,Jigsaw 是 JDK8 的一部分,它还没有完全准备好。它预计要到 2013 年 1 月才能完成功能,并且不会在 2013 年年中之前发布。

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

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

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

这里只有名为 bar 或 baz 的模块需要模块 foo。某个其他名称的模块对 foo 的依赖在编译时、安装时或运行时将无法解决。如果不存在许可条款,则不存在此类约束。

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

没有 Jigsaw 的OSGi的问题在于,框架强制执行的任何规则都可以通过反射来破坏,但是一旦 Jigsaw 准备好供公众使用,这些规则将由 Java 本身强制执行,正如您在上面阅读的那样,在编译时,运行时间和安装时间。

于 2012-06-12T02:54:15.953 回答
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 版本或其他东西。

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

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

由于您对 OSGi 不太熟悉,因此我建议您先使用选项 1,然后如果需要,您可以稍后将您的方法升级到选项 3。

@Edwin Dalorzo:OSGi 中的规则可以通过反射来破坏,这绝对不是真的。Bundle 在 OSGi 中有单独的类加载器。您可以从 Bundle C 中尽可能多地反映 A 类,而您唯一会得到的是 ClassNotFound 异常 - 相信我,我已经看过很多次了;)

于 2012-06-14T10:34:20.983 回答