我是Java的新手。我发现,在尝试构建我的代码时,Java将源文件组织(目录结构)与包结构和包结构紧密地联系到类的外部可见性(一个类对所有其他包可见,或者没有)。 / p>
这使我很难将公共库的内部实现细节组织成相关功能的逻辑单元,同时保持良好的封装。 JSR 294解释得最好:
今天,可以将实现划分为多个包。 这种实现的子部分需要更紧密地耦合 彼此不同于周围的软件环境。今天 设计师被迫宣布该计划的元素 实施的其他子部分需要公共 - 从而 使它们在全球范围内可访问,这显然不是最理想的。
或者,整个实现可以放在一个单独的实现中 包。这解决了上面的问题,但是很笨拙,而且暴露了 所有子部分的所有内部结构。
所以我的问题是,这种限制存在哪些变通方法,以及什么是优点和缺点。利弊? JSR中提到了两个 - 使用包进行逻辑分组(违反封装);把所有东西放在一个包里(笨重)。这些变通办法还有其他优点/缺点吗?还有其他解决方案吗? (我已经模糊地意识到OSGi捆绑包,但我发现很难理解它们是如何工作的以及优点/缺点可能是什么(也许这是一个骗局)。似乎是与香草包相比,对于开发和部署而言非常具有侵入性。
注意:我会提供任何好的答案,但最佳答案将是在专业人士和答案中全面折叠的答案。其他人的弊端(抄袭!)。
预计“可能重复”的声音,这里是我在SO上发现的类似的问题;我在这里介绍它们以供参考,并解释为什么它们不回答我的问题。
答案 0 :(得分:0)
ProGuard之类的工具可用于重新打包JAR,只展示您在配置文件中指定的那些类。 (除了优化,内联和混淆之外,它还可以执行此操作。)您可以在例如中设置ProGuard。 Maven或Ant构建,因此您将库公开方法编写为公共方法,然后使用ProGuard将其从生成的JAR中删除。
答案 1 :(得分:0)
我会让球滚动。窃取这个答案并添加/纠正/请详细说明!
优点:相关代码的有效逻辑分组。
缺点:当不同包中的内部实现详细信息类需要相互使用时,必须将它们公开 - 甚至是最终用户 - 违反封装。 (通过对包含内部实现细节(如.internal或.impl)的包使用标准命名约定来解决此问题。)
优点:有效封装
缺点:如果库包含很多类,那么它对于库的开发/维护是不实用的
优点 :? (他们解决了这个问题吗?)
缺点:与仅部署.jar文件相比,在开发(对于库用户和作者)和部署方面似乎非常具有侵入性。
http://openjdk.java.net/projects/jigsaw/
优点:解决问题的好处?
缺点:尚不存在,不知道具体的发布日期。
答案 2 :(得分:0)
我从未发现这是一个问题。解决方法(如果你想称之为)称为良好的API设计。
如果您的图书馆设计得很好,那么您几乎总能做到以下几点:
因此,对于我来说,包的“正确级别的封装”是为了暴露足够的公共API,使您的包可以有效地用作依赖。不多也不少。它是否被同一个库中的另一个包或外部用户使用并不重要。如果围绕这个原则设计包装,就会增加有效重复使用的机会。
只要您的API设计合理,使一部分软件包“全局可访问”真的不会造成任何伤害。请记住,包不是对象实例,因此封装并不重要:将包的元素公开通常 比暴露类的内部实现细节(我是同意应该几乎总是私密/受保护)。
例如考虑java.lang.String。它有一个很大的公共API,但无论你使用公共API做什么都不能干扰java.lang.String的其他用户。从多个地方同时使用作为依赖关系是完全安全的。另一方面,如果你允许java.lang.String的用户直接访问内部字符数组(这将允许不可变字符串的就地变异......讨厌!!),所有地狱都会破裂。
P.S。值得一提的是OSGi,因为它是一种非常棒的技术,在许多情况下非常有用。然而,它的最佳点在于模块的部署和生命周期管理(停止/启动/加载等)。代码组织恕我直言,你真的不需要它。