我们使用对集合的接口引用。它只是为了良好的编码实践还是背后有一些逻辑?谁能解释一下?
例如:
我们用
Map<String, Integer> map = new HashMap<String,Integer>();
代替
HashMap<String, Integer> map = new HashMap<String,Integer>();
我们使用对集合的接口引用。它只是为了良好的编码实践还是背后有一些逻辑?谁能解释一下?
例如:
我们用
Map<String, Integer> map = new HashMap<String,Integer>();
代替
HashMap<String, Integer> map = new HashMap<String,Integer>();
如果您使用HashMap
您的实现变得特定于,HashMap
但如果您使用Map
,您可以在将来将其更改为任何Map Implementation
。
您可以阅读第 52 条:从 Effective Java 中通过接口引用对象。
拥有interface
将允许您在未来透明地更改实现(在客户端没有很多更改)。
例如:
Map<String, Integer> map = new LinkedHashMap<String,Integer>();
即使您将实现更改为 LinkedHashMap,客户端也不需要对其进行任何更改。
如果你使用
HashMap<String, Integer> map = new HashMap<String,Integer>();
客户端与实现紧密耦合。如果您更改实现,那么您还需要更改客户端。
一个缺点是,如果您想使用任何特定于实现的方法,您需要转换为相应的类型并使用它。
这个想法是您对组件的合同进行编码,而不是对实现进行编码。java.util.Map 有许多实现,如果您的代码完全依赖于接口,可以在需要时无缝互换。
一般来说,松散耦合是一种很好的做法。
代码维护是一个优势,如果有人想使用其他具体的代码Map
,您只需更改一行而不是数十行。在您的代码片段示例中似乎并非如此,只有当对象引用的使用在参数和返回类型中变得普遍时才会出现问题。我认为最好从一开始就开始“考虑接口”而不是对象,以避免编写带来这些问题的代码的趋势。在这里引用Allen Hollub
如果您编写的客户端代码只关注接口所保证的功能,而不是特定类的实际实现,那么您将来将有更多的自由来更改实现。
如下所示 -
class MapTest {
Map<String, Integer> map;
public MapTest(Map<String, Integer> map) {
this.map = map;
}
public void setMap(Map<String, Integer> map) {
this.map = map;
}
//do stuffs with map
}
你可以传入不同的实现Map
。但是如果map
是类型,HashMap
那么它总是必须是一个HashMap
(或者如果你将它子类化,它就是子类)。
第一种方法比第二种方法灵活得多:
Map<String, Integer> map = new HashMap<String,Integer>();
这样,如果您决定改用 a ,则只需更改一行TreeMap
。
此外,对集合进行操作的方法应指定类型的参数Map
:
public static void print(Map<String, Integer> s)
然后该方法可用于所有地图实现。
理论上,我们应该对链表提出同样的建议,即将LinkedList
引用保存在类型为 的变量中List
。