我有一个图书馆,里面有几个包裹
可以说
包装
包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,因此这并不是真正的担心。