Java:在jar文件中只显示一个包

我想要一个只能访问API包的jar文件。 所有其他包(包含实现)都不会被另一个jar(也不是任何其他类)访问。

可能吗 ?

如果有,怎么样?

目前计划用于Java 8(2012?)的是JSR 294 。 这个JSR将更好的模块化语言结构引入Java。

今天,可以将实现划分为多个包。 这种实现的子部分需要彼此更紧密地耦合,而不是与周围的软件环境相互耦合。 今天,设计师被迫将实施的其他子部分所需的程序元素声明为公共部分 – 从而使它们在全球范围内可访问,这显然不是最理想的。

或者,整个实现可以放在一个包中。 这解决了上面的问题,但是不实用,并且将所有子部件的所有内部部件相互暴露。

设想的语言变化将解决这些问题。 特别是,我们希望在语言层面引入一个新的模块概念( 超级包 ),其中现有的公共访问控制仅适用于语言级模块,并且模块外部对API的访问将仅限于模块明确导出的API。

现在我相信专家组仍在讨论这个概念的细节。 但我相信你可以做的一件事就是这个(源代码: Java 7.0中的超级软件包 ):

 superpackage com.myorg.myApp.model { member package com.myorg.myApp.model.swing; member package com.myorg.myApp.model.html; export com.myorg.myApp.model.swing.SEmployee; export com.myorg.myApp.model.swing.SDepartment; export package com.myorg.myApp.model.html; } 

换句话说,对于给定的“超级包”,您可以定义什么是导出和不导出,独立于public可见性关键字。

如果您有不应使用的类,请将它们放入名为“internal”的子包中。 虽然这并不妨碍其他人使用这些课程,但强烈表明他们不应该这样做。

例:

 my.library.Stuff my.library.StuffFactory my.library.internal.StuffImpl my.library.internal.MoreStuff my.library.internal.xml.DataStuff 

虽然这不是一个实际的解决方案,但我认为这是一种最佳实践。

这在Java 6中是不可能的,除非你使用OSGI,我认为你不是。 我通常最后做的隐藏类的方法是使用包友好类来实现 – 但如果你的实现类确实存在于一个单独的包中,你可能仍然需要公开一些类。

样品:

package com.example;

public class Service { }假设API类使用ServiceImpl作为其实现

现在,如果ServiceImpl位于同一个包中,您可能会删除它的公共类修饰符,并且无法在包外部访问它…

如果它生活在一个不同的包(你的情况),它需要公开:

package com.example.impl;

public class ServiceImpl { }

但是同一个包中的所有实现细节(它使用的相关类)都不需要公开!

在一个“正常”的Java应用程序中是不可能的。 虽然在OSGi环境中,您可以定义捆绑包(稍微修改过的jar文件)向其他捆绑包公开哪些包,哪些包是私有的(在捆绑包外部不可见)。

为什么不简单地创建一个带有API类的jar和一个带有依赖于API的实现的分离jar。 这样,您可以在不分发实现的情况下分发API类。

KR。

我可以看到你为什么要这样做的原因。 当我尝试使用某人的图书馆时,它一直困扰着我。 有很多课程,我不知道从哪里开始。

据我所知,大多数图书馆都没有这样的图书馆试图隐藏不相关的类。 虽然这不是一个确凿的证据,但它必然意味着没有办法做到这一点。 通常,他们将api和实现发布到分离的jar文件中。

但是,如果您通过OSGi框架运行应用程序,则可以捆绑您的jar文件,使OSGi框架只能看到您想要的API类。 但是使用OSGi可能有点工作。

您可以添加ant-task或maven-jar-plugin配置,根据您的构建工具首选项来包装您需要的组件。

另一种解决方案是在实现类中设置默认访问修饰符,并将它们放在与接口相同的包中。 虽然它有点脏。