我有一个图书馆,里面有几个包裹

可以说
包装
包b;

内包装一个我有公共(public)a_class
在包b中,我有公共(public)b_class
a_class使用b_class。

我需要从中生成一个库,但是我不希望客户端看到b_class。

我知道的唯一解决方案是将我易于理解的软件包简化为单个软件包,并对b_class使用默认的软件包访问权限。
还有其他方法吗?也许使用接口(interface)或某种形式的设计模式?

最佳答案



是的,使b_class package-private(默认访问)并通过反射实例化它以用于a_class

由于您知道完整的类名,因此可以反射地加载类:

Class<?> clz = Class.forName("b.b_class")

找到您要调用的构造函数:
Constructor<?> con = clz.getDeclaredConstructor();

允许自己通过使其可访问来调用构造函数:
con.setAccessible(true);

调用构造函数以获取b_class实例:
Object o = con.newInstance();

Hurrah,现在您有了b_class的实例。但是,您不能在b_class实例上调用Object的方法,因此有两个选择:
  • 使用反射来调用b_class的方法(虽然不太有趣,但是很简单,如果您只有少数几个带有少量参数的方法,那就可以了)。
  • b_class实现一个您不介意客户端看到的接口(interface),并将您的b_class实例强制转换为该接口(interface)(在两行之间阅读,我怀疑您可能已经有了这样的接口(interface)?)。

  • 您肯定希望使用选项2来最大程度地减少痛苦,除非它使您再次陷入困境(用不想向客户端公开的类型来污染 namespace )。

    为了全面披露,有两个注意事项:

    1)使用反射与直接实例化和调用相比,开销很小。如果转换为接口(interface),则只需支付实例化的反射成本。在任何情况下,除非您在一个紧密的循环中进行成千上万次调用,否则可能都不是问题。

    2)没有什么可以阻止确定的客户端找出类名并执行相同的操作,但是如果我正确理解了您的动机,则只想公开一个干净的API,因此这并不是真正的担心。

    07-24 09:46
    查看更多