包装和可见性

Posted

技术标签:

【中文标题】包装和可见性【英文标题】:Package and visibility 【发布时间】:2012-01-28 16:09:49 【问题描述】:

我正在制作一个 SDK,我正在尝试将类分离到不同的包中,这些类使用其他一些共享类。问题是如果我公开共享课程,每个人都可以看到它们,而不仅仅是我的课程。使它们只能由我的应用程序访问的正确方法是什么?

例子:


包装一个 我的班级1

包 b 我的班级2

包c 公共MySharedClass


因为 c 是公共的 MySharedClass 将能够访问它,但问题是它也将对世界可见,我该如何防止呢?

【问题讨论】:

可能重复:***.com/questions/4388715/… 【参考方案1】:

创建一个记录为内部包的包,不供客户使用。

在 Java 中没有办法只为某些包公开一个类:它要么是 public 要么对所有人或 package-private(只在声明的包中公开)。

我认为有一个关于模块的提议,以允许更好地控制类的可见性,但我们至少要等待 Java 8。

【讨论】:

+1 另见 ***.com/questions/4903879/… 和 Java 8 模块 == Jigsaw slideshare.net/mfrancis/…【参考方案2】:

Java 中的包都是“公共的”,您可以保护的是包中的类。要将类的可见性限制为仅给定的包,请像这样声明它(没有 public 可见性修饰符):

class MyClass 
    // ...

这样,只有与 MyClass 在同一个包中的类才能看到它。

【讨论】:

但是通过这样做,我必须将所有使用该类的类移动到同一个包中。如果可能的话,这是我试图避免的。 是的。以这样一种方式构建您的项目,即所有 internal(非公共)类都组合在一系列包中,而公共类则在其他包中。您可以通过公共包中的公共外观公开内部类的功能。【参考方案3】:

不平凡:

共享类可以由一组一般可访问的接口定义。实际的实现应该通过Classloader 显式加载。之后,只需应用 Java 安全管理机制来控制对实现类的访问。任何人都可以看到接口,并且对实际实现的访问将仅限于您的 SDK。

(上面的一个变体是每个 web/app 服务器都需要做的。你认为 Tomcat 是如何阻止你访问其他应用程序的“公共”类的?)

edit:上面的注释是一个运行时机制。还有静态(后)编译方法。例如,APT 在这里可能很有效。自然,我不是在解决您的包的重组(在 OP 中),而只是解决如何保护对一般方法的访问。但这些有点“hacky”——类加载的运行时机制是规范的,而且 imo 严格来说更正确。

【讨论】:

【参考方案4】:

如果该类被来自两个不同包的类共享,这可能是一个很好的迹象,表明这两个类应该在同一个包中,以及共享类,它不会是公共的,因此只能使用按同一包的类。

如果实在不行,只需适当地记录共享类,以表明它不应该在 SDK 内部代码之外使用,它可能会在未来版本中发生变化,并通过命名包“内部”或类似的东西。

【讨论】:

如果需要,您甚至可以在之后混淆您的内部类。您的客户仍然可以看到,但不再真正可用。另外,只为你的非内部类生成 javadoc,这让客户很明显不要依赖你的内部类【参考方案5】:

可以使用受保护的修饰符,以防您的类只能在同一个包中访问。否则没有可能。

【讨论】:

以上是关于包装和可见性的主要内容,如果未能解决你的问题,请参考以下文章

可见性原子性有序性

IE10:“可见性:可见”在“可见性:隐藏”元素的伪元素之前

Flutter 中的不可见性、消失、可见性 ROW 和列

volatile关键字原子性和可见性

关于变量的可见性和生命周期

原子性、可见性、有序性