PMD将报告以下违规行为:
ArrayList<Object> list = new ArrayList<Object>();
违反是“避免使用类似'ArrayList'的实现类型;而是使用接口”。
以下行将纠正违规:
List<Object> list = new ArrayList<Object>();
为什么要用后者List
代替ArrayList
?
Answers:
总的来说,我同意将接口与实现分离是一件好事,它将使您的代码更易于维护。
但是,您必须考虑一些例外情况。通过接口访问对象会增加一个间接层,这会使您的代码变慢。
出于兴趣,我进行了一个实验,该实验产生了对100万个长度ArrayList的100亿次顺序访问。在我的2.4Ghz MacBook上,通过List接口访问ArrayList的平均时间为2.10秒,而将其声明为ArrayList类型则平均花费了1.67秒。
如果要处理大型列表,深入内部循环或经常调用的函数,则需要考虑这一点。
为什么要使用带有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).*/
要么
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.*/
要么
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
要么
其他一些List
特定的实现。
List
接口定义合同,并且List
可以更改特定的实现。这样,接口和实现就松散地耦合在一起。
相关的SE问题:
通常,对于您的代码行,不必理会接口。但是,如果我们谈论的是API,则有充分的理由。我上小班
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
在这种情况下,需要使用接口。因为我想计算每个可能的实现的大小,包括我自己的自定义。class MyList extends AbstractList<String>...
。