应该始终使用Java中的接口声明变量吗?

Pet*_*Pro 7 java declaration list

人们常常看到变量应该用某个接口声明的建议,而不是实现类.例如:

List<Integer> list = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

但是,假设我使用此列表来实际依赖于ArrayList(例如Fisher-Yates shuffling)的O(1)随机访问的算法.在这种情况下,ArrayList代表我的关键抽象是它的数组性质,而不仅仅是它的List性质.换句话说,如果某人出现并更改list为a LinkedList,即使代码可以编译,也会出现问题.在这种情况下,声明是否可以使用实现类型?,例如:

ArrayList<Integer> list = new ArrayList<>(); 
Run Code Online (Sandbox Code Playgroud)

Mar*_*o13 3

强调一下 Oliver Charlesworth 在评论中所说的话:最关键的区别是这些信息是否公开。

从问题的编写方式来看,您似乎在谈论一个字段(而不是方法参数或返回值)。根据定义,私有字段是一个实现细节,您可以任意指定它。因此,将其声明为ArrayList- 尽管严格来说,这是不相关的。这么说吧:你说

如果有人...改为lista LinkedList,这就会有问题,...

可以更改声明的人

private List<T> list = new ArrayList<T>();
Run Code Online (Sandbox Code Playgroud)

private List<T> list = new LinkedList<T>();
Run Code Online (Sandbox Code Playgroud)

还可以更改声明

private ArrayList<T> list = new ArrayList<T>();
Run Code Online (Sandbox Code Playgroud)

private LinkedList<T> list = new LinkedList<T>();
Run Code Online (Sandbox Code Playgroud)

防止这种情况的唯一实用方法是将这个(重要的)实现细节添加为注释,例如

/**
 * The list that stores ... whatever. 
 *
 * This list should have a complexity of O(1) for random access,
 * because ...
 */
private final List<T> list = new ArrayList<T>();
Run Code Online (Sandbox Code Playgroud)

(这也可以通过在内部将列表传递给一个期望它是 的方法来强制执行RandomAccess。这是由 AlexR 提出的,但指的是public方法。对于private方法,即使这也不会阻止某人更改方法签名,如果没有记录意图和要求的原因)。RandomAccess