【问题标题】:Providing Java library, but hiding some classes提供Java库,但隐藏一些类
【发布时间】:2011-07-10 18:10:41
【问题描述】:

我正在使用 Java ME 开发一个应用程序,我想将其作为库提供。有没有办法隐藏我不希望每个人都使用的类,但对于图书馆的工作来说仍然是必不可少的?

更新: 我知道我可以省略公共说明符,但是如何在开发时构建库本身而不创建不同的包?我喜欢将不同的包简单地视为不同的文件夹,这使我能够以一种好的方式构造代码。但是,在某些情况下,我可能需要访问其他包中的类,所以这相当棘手。包真正代表什么?一种想法可能是创建“接口”,但必须将它们声明为 public,这意味着外国人也可能实现仅用于库内某些进程的接口,对吗?

【问题讨论】:

  • 使类最终化只会禁止子类化它。它仍然会暴露。
  • 取决于您所说的“想要”是什么意思以及您想要解决多少麻烦。例如,访问修饰符很容易通过反射来解决。
  • 是的,但是当我在 Eclipse 中包含我的 API 的 jar 文件时,如果我展开 jar 文件的内容,所有类都会显示出来。因此,我想将它们宣布为最终解决方案的一部分,以真正防止任何人使用它们。但是如果我有一个 API,也许我也想在 API 中包含不同的包。但是在没有 public 修饰符的情况下声明它们意味着我无法访问我想要的 API 的不同部分。创建不同包的“正常”原因是什么?我的意思是,我可以将所有代码放在同一个包中,但库的结构不会很结构化......

标签: java java-me


【解决方案1】:

为了设置您的库 API,您需要保护您的任何内容 不想暴露。这样做只是省略访问修饰符:

class fooBar {
    // do stuff here    
}

这会将类访问设置为“默认”,允许从 在同一个包内以及来自任何子类的类 fooBar.

在您的类中,您还希望通过将方法和成员标记为privateprotected 或省略修饰符来锁定对方法和成员的任何访问权限,以便根据需要将它们设为“默认”。

  • private 将只允许从包含的类进行访问;
  • 'default'(无修饰符)允许来自包含类和包含包;和
  • protected 将允许从同一类、包和任何子类中进行访问。

对于您公开的任何内容 (public),如果它不是被设计为被覆盖的,那么将其标记为 final 也是一种好习惯。

基本上,尽可能地锁定一切。较小的 API 更易于使用且更难破解。如果您发现将来需要公开某些内容,请在将来进行。扩展 API 比弃用 API 的一部分要容易得多。

【讨论】:

  • 谢谢!但正如你所说,我只能在同一个包中使用类 fooBar 。构建 Java 项目的常用方法是什么?我一直在根据类所做的不同事情创建包。例如,我有一个名为 com.comms 的包,我在其中存储用于通过套接字传输的例程和类。然后我有另一个使用 comms 包的包(如应用程序级别)。但我想,为了创建这样的 API,我应该将所有类都放在同一个包中?
  • 是的,当你有一个包含多个包的库时怎么办?
  • 默认情况下,类具有默认可见性,因此可见性仅在包内。您还可以将其设置为显式保护,它也将用于相同的目的,
【解决方案2】:

您可以创建只有同一包中的其他类才能看到的类package protected。 如果这不可行,那么您可以使用ProGuard 来破坏类并隐藏它们的实现。

【讨论】:

  • 谢谢,是的,我会调查 ProGuard
  • 您不能将protected 修饰符用于类,只能用于成员。限制对您的类的访问的唯一方法是省略 public 修饰符,使其仅在其包中可见。
【解决方案3】:

如果可以使用 Java 9,请使用 Jigsaw modules。如果没有,请将每个类放在同一个包中,对隐藏类具有包级访问权限,并使用Maven modules 来组织它们。

我在名为coronata 的项目中完全做到了这一点,这是一个Wii Remote java 库。几乎所有的类都在包 com.github.awvalenti.bauhinia.coronata 中,但在不同的模块上(在 IDE 中显示为项目)。

可见类是公开的。它们在模块中:

  • coronata-api
  • coronata-builder
  • coronata-demos
  • coronata-lib

隐藏类具有包级别的访问权限。它们在模块中:

  • coronata-common
  • coronata-implementation-bluecove
  • coronata-implementation-wiiusej

【讨论】:

    【解决方案4】:

    让我们考虑一个例子:

    如果您有一个要隐藏的 A 类和一个使用 A 类功能的 B 类,那么您可以这样做:

    class B{
    //Attribute and Methods
    
        //Inner class A
        class A{
          //Methods and Attributes.
        }
    
    }
    

    完成此操作后,您可以在 B 类的方法中创建 A 类的 Object 并使用它。尽管该类将对其他类隐藏,但仍然可以使用。

    【讨论】:

    • 创建一个内部类并不会向外界隐藏它。您仍然可以导入并使用它。但是,您使用的包级访问权限将隐藏其他包中的类。
    【解决方案5】:

    是的,有。

    不要声明这些类public。换句话说,省略 public 关键字,如下所示:

    class Internal { // rather than "public class Internal"
        ...
    }
    

    默认情况下,类只能在定义它们的包中访问。

    【讨论】:

      【解决方案6】:

      您需要对不想暴露的类进行保护。这将使它们无法从客户端代码中使用。阅读更多the official docs

      【讨论】:

      • 你需要的部分:在类声明中省略'public'关键字,那么该类只能被同一个包中的其他类访问。​​
      • 您不能将protected 修饰符用于类,只能用于成员。限制对类的访问的唯一方法是省略 public 修饰符,使其仅在其包中可见。
      猜你喜欢
      • 2011-11-30
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2013-11-21
      • 2020-06-30
      • 1970-01-01
      • 2014-12-09
      • 1970-01-01
      相关资源
      最近更新 更多