题
PMD 会报告违规行为:
ArrayList<Object> list = new ArrayList<Object>();
违规是<!>;避免使用像'ArrayList'这样的实现类型;使用界面改为<!> quot;。
以下行将更正违规行为:
List<Object> list = new ArrayList<Object>();
为什么后者用List
代替ArrayList
?
解决方案
在具体类型上使用接口是良好封装和松散耦合代码的关键。
在编写自己的API时,遵循这种做法甚至是个好主意。如果你这样做,你会发现稍后会更容易将单元测试添加到代码中(使用模拟技术),并在将来需要时更改底层实现。
这是关于的好文章主题。
希望它有所帮助!
其他提示
这是首选,因为您将代码与列表的实现分离。使用该接口,您可以轻松地将实现(在本例中为ArrayList)更改为另一个列表实现,而无需更改任何其余代码,只要它只使用List中定义的方法。
总的来说,我同意将接口与实现分离是一件好事,并且会使代码更易于维护。
但是,您必须考虑例外情况。通过接口访问对象会增加一个额外的间接层,使您的代码变慢。
为了兴趣,我进行了一项实验,该实验产生了对100万长度ArrayList的100亿次顺序访问。在我的2.4Ghz MacBook上,通过List接口访问ArrayList的平均时间为2.10秒,当声明类型为ArrayList时,它平均需要1.67秒。
如果您正在处理大型列表,内部循环内部或经常调用的函数,则需要考虑这一点。
ArrayList和LinkedList是List的两个实现,它是一个有序的项集合。逻辑方面,如果使用ArrayList或LinkedList并不重要,所以不应该将类型约束为。
这与“收集”和“列表”形成鲜明对比,后者是不同的东西(列表意味着排序,收集不会)。
为什么后者使用List而不是ArrayList?
这是一个很好的做法:程序接口而不是实现
将ArrayList
替换为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
其他一些<=>具体实施。
<=>接口定义合同,<=>的具体实现可以更改。通过这种方式,接口和实现松散耦合。
相关的SE问题:
即使对于局部变量,使用具体类的接口也有帮助。您最终可能会调用接口外部的方法,然后在必要时很难更改List的实现。 此外,最好在声明中使用最不具体的类或接口。如果元素顺序无关紧要,请使用Collection而不是List。这为您的代码提供了最大的灵活性。
您的类/接口的属性应该通过接口公开,因为它为您的类提供了一个行为契约,无论其实现如何。
...然而
在局部变量声明中,这样做没有意义:
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
如果是局部变量,只需使用该类型即可。它仍然可以隐式地向上转换为其适当的接口,并且您的方法应该有希望接受其参数的接口类型,但对于局部变量,将实现类型用作容器是完全合理的,以防万一您确实需要实现 - 具体功能。
一般来说,对于您的代码行,打扰接口是没有意义的。但是,如果我们谈论API,那就有一个很好的理由。我上了小班
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
在这种情况下,需要使用接口。因为我想计算每个可能的实现的大小,包括我自己的自定义。 class MyList extends AbstractList<String>...
。