PMD会报告违规行为:
ArrayList<Object> list = new ArrayList<Object>();
违规是“避免使用像'ArrayList'这样的实现类型;而是使用界面”。
以下行将更正违规行为:
List<Object> list = new ArrayList<Object>();
为什么后者使用List
代替ArrayList
?
答案 0 :(得分:75)
在具体类型上使用接口是良好封装和松散耦合代码的关键。
在编写自己的API时,遵循这种做法甚至是个好主意。如果你这样做,你会发现稍后会更容易将单元测试添加到你的代码中(使用模拟技术),并在将来需要时更改底层实现。
这是关于这个主题的good article。
希望它有所帮助!
答案 1 :(得分:28)
这是首选,因为您将代码与列表的实现分离。使用该接口,您可以轻松地将实现(在本例中为ArrayList)更改为另一个列表实现,而无需更改任何其余代码,只要它仅使用List中定义的方法。
答案 2 :(得分:12)
总的来说,我同意将接口与实现分离是一件好事,并且会使代码更易于维护。
但是,您必须考虑例外情况。通过接口访问对象会增加一个额外的间接层,使您的代码变慢。
为了兴趣,我进行了一项实验,该实验产生了对100万长度ArrayList的100亿次顺序访问。在我的2.4Ghz MacBook上,通过List接口访问ArrayList的平均时间为2.10秒,当声明类型为ArrayList时,它平均需要1.67秒。
如果您正在处理大型列表,内部循环内部或经常调用的函数,则需要考虑这一点。
答案 3 :(得分:6)
ArrayList和LinkedList是List的两个实现,它是一个有序的项集合。逻辑方面,如果使用ArrayList或LinkedList并不重要,所以不应该将类型约束为。
这与“收集”和“列表”形成鲜明对比,后者是不同的东西(列表意味着排序,收集不会)。
答案 4 :(得分:2)
为什么后者使用List而不是ArrayList?
这是一个很好的做法:程序接口而不是实现
将ArrayList
替换为List
,您可以在以后更改List
实施,具体取决于您的业务用例。
List<Object> list = new LinkedList<Object>();
/* Doubly-linked list implementation of the List and Deque interfaces.
Implements all optional list operations, and permits all elements (including null).*/
OR
List<Object> list = new CopyOnWriteArrayList<Object>();
/* A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/
OR
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
OR
其他一些List
具体实现。
List
接口定义了合同,List
的具体实现可以更改。通过这种方式,接口和实现松散耦合。
相关的SE问题:
答案 5 :(得分:1)
一般来说,对于您的代码行,打扰接口是没有意义的。但是,如果我们谈论API,那就有一个很好的理由。我上了小班
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
在这种情况下,需要使用接口。因为我想计算每个可能的实现的大小,包括我自己的自定义。 class MyList extends AbstractList<String>...
。
答案 6 :(得分:1)
您的类/接口的属性应该通过接口公开,因为它为您的类提供了一个行为契约,无论其实现如何。
...然而
在局部变量声明中,这样做没有意义:
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
如果是局部变量,只需使用该类型即可。它仍然可以隐式地向上转换为其适当的接口,并且您的方法应该有希望接受其参数的接口类型,但对于局部变量,将实现类型用作容器是完全合理的,以防万一您确实需要实现 - 具体功能。
答案 7 :(得分:1)
即使对于局部变量,使用具体类的接口也有帮助。您最终可能会调用接口外部的方法,然后在必要时很难更改List的实现。 此外,最好在声明中使用最不具体的类或接口。如果元素顺序无关紧要,请使用Collection而不是List。这为您的代码提供了最大的灵活性。
答案 8 :(得分:0)
接口向最终用户公开。一类可以实现多个接口。暴露于特定界面的用户可以访问该特定界面中定义的某些特定行为。
一个接口也有多种实现。基于该方案的系统将与不同的方案一起工作(接口的实现)。
让我知道是否需要更多说明。
答案 9 :(得分:0)
在调试器视图中,接口通常比具体的类具有更好的表示形式。