在Java中,是否可以声明其类型为多个接口的字段/变量?例如,我需要声明一个Map也是Serializable.我想确保变量引用可序列化的映射.该Map接口不延长Serializable,但大部分Map的实现是Serializable.
我很确定答案是否定的.
后续:我充分意识到创建同时扩展新的界面Map和Serializable.这不起作用,因为现有的实现(例如HashMap)不实现我的新接口.
ska*_*man 12
你可以用泛型来做,但它不漂亮:
class MyClass<T,K,V extends Serializable & Map<K,V>> {
T myVar;
}
Run Code Online (Sandbox Code Playgroud)
没有必要像这样声明字段/变量.特别是因为它只能测试运行时而不是编译时间.如果传递的Map没有实现Serializable,则创建一个setter并报告错误.
建议您创建自己的界面的答案当然不是很实用,因为他们会主动禁止发送Maps和Serializable但不是您的特殊界面.
使用一些泛型技巧可以做到这一点:
public <T extends Map<?,?> & Serializable> void setMap(T map)
Run Code Online (Sandbox Code Playgroud)
上面的代码使用泛型来强制您传递实现两个接口的映射.但请注意,这样做的结果是,当您实际传递地图时,它们可能需要标记为可序列化或已经可序列化的地图类型.阅读起来也相当困难.我会记录地图必须是可序列化的并执行测试.
public interface MyMap extends Map, Serializable {
}
Run Code Online (Sandbox Code Playgroud)
将定义一个新的界面,联盟Map和Serializable.
您显然必须提供一个合适的实现(例如MyMapImpl),然后您可以提供类型的变量引用MyMap(或Map,或Serializable,根据要求).
为了解决您的问题,您无法改进行为(例如,可序列化的地图).您必须具有接口和一些适当的实现.
我投票赞成布莱恩的答案,但想添加一些更高层次的想法。
如果您仔细查看 SDK,您会发现它们很少(如果有的话)传递实际的集合对象。
原因是这不是一个好主意。收藏品极不受保护。
大多数时候,您希望在传递它之前制作一个副本并传递该副本,以便对集合的任何修改都不会改变依赖它的其他东西的环境。而且,线程变成了一场噩梦——即使使用同步集合!
我见过两种解决方案,一种是始终提取数组并传递它。SDK 就是这样做的。
另一种是始终将集合包装在父类中(我的意思是封装,而不是扩展)。我已经养成了这个习惯,这是非常值得的。它实际上并不需要任何成本,因为无论如何您都不会复制所有收集方法(实际上您很少复制其中任何一个)。事实上,您最终要做的是将“实用程序”功能从分布在整个代码中的其他类移动到包装类中,这才是它应该放在首位的位置。
任何具有与“method(collection,...)”匹配的签名的方法几乎肯定应该是该集合的成员方法,任何迭代该集合的循环也应该如此。
我只是不得不时不时地把它扔掉,因为这是我有一段时间没有得到的东西之一(因为没有人支持这个概念)。它似乎总是有一些缺点,但已经这样做了一段时间,看到它解决的问题并消除了代码,我自己甚至无法想象任何可能的缺点,这一切都很好。
| 归档时间: |
|
| 查看次数: |
6993 次 |
| 最近记录: |