以下是两种创建方法ArrayList
:
List<String/*or other object*/> arrList = new ArrayList();//Imports List, ArrayList
ArrayList<String/*or other object*/> arrList = new ArrayList();//Imports just ArrayList
有什么区别?应该使用哪种方法?
建议将第一种形式用于类的公共接口(例如,在类中声明属性)。这是一个众所周知的建议,您应该为接口而不是具体实现进行编程(这在设计模式中有所说明) - 您必须导入的类的数量与代码的质量和良好的设计几乎没有关系。
第一种形式的优点是,如果需要,它可以让您在以后轻松地交换实现 - 而第二种实现固定实现类,使您的代码更难发展,更不灵活。
但是,在某些情况下,可以声明和使用具体类(例如,为了稍微提高性能)。但是一个类的公共接口应该尽可能使用接口,这将使未来的变化更容易实现。
第一种方法称为接口编码
第二个称为实现编码。
第二个的优点是它使您可以灵活地在以后更改实现类,而无需更改任何代码。例如,今天您正在使用ArrayList
,但如果明天您想将其更改为,LinkedList
则只需更改列表定义中的实现类。
通过像第一个示例一样执行此操作,您可以将 List 分配给实现该List
接口的任何数据结构。
这会增加flexibility
您的程序,因为您可以轻松更改实现。
如果您后来意识到 List 的另一个实现更适合您的任务,第一个让您可以自由更改具体类 (ArrayList)。您只需要更改这一行,因为其他地方使用arrList
期望任何实现 List,而不是ArrayList
.
在第二个版本中,如果您决定进行更改,您将不得不更改每个期望ArrayList.
如上所述,这称为接口编码。
与流行的观点相反,我说我们应该使用第二种形式
ArrayList<X> list = new ArrayList<>();
这一行是一个实现细节;我们应该在我们的实施细节中尽可能具体。
它不是应该抽象的公共 API 的一部分;“针对接口的代码”的参数不适用于此处。
列表是一个接口。ArrayList 是一个实现 List 接口的类。
不同之处在于它对返回 List 的方法的调用者隐藏了特定的实现。这通常是一种很好的做法——如果您返回List
,那么您以后可以自由地更改底层实现,而不必担心更改一堆其他代码的连锁反应。如果您不需要特定于列表的内容,List.get(index)
您甚至可以更进一步,只需指定Collection<String> col = new ArrayList<String();
如果你想创建一个ArrayList
,只有第二个是正确的。第一个创建 a List
,由ArrayList
类实现,但在许多情况下它们不可互换。这个问题有一个很好的答案。
我可以看到很多人建议使用该界面,我会说以下内容:
如果您认为使用您的代码的人确实需要知道您正在使用的实现的细节,请使用具体类。例如,如果您正在编写一个高性能库,该库具有返回特定实现的方法,例如 LinkedList,在处理时需要特别小心)..
在大多数其他情况下,当您可以避免暴露太多细节时,请使用接口。