One often sees the advice that variables should be declared with some interface, not the implementing class. For example:
List<Integer> list = new ArrayList<>();
However, say I am using this list for an algorithm that really depended on the O(1) random access of an
ArrayList (e.g. Fisher-Yates shuffling). In that case, the key abstraction that
ArrayList represents for me is its array-like nature, not just its List nature. In other words, if someone came along and changed
list to a
LinkedList, this would be problematic, even though the code would compile. In such a case, is it considered ok to have the declaration use the implementation type?, e.g.:
ArrayList<Integer> list = new ArrayList<>();
Best How To :
To emphasize what Oliver Charlesworth said in the comment: The most crucial difference whether this information is public or not.
From the way how the question is written, it seems like you're talking about a field (and not a method parameter or return value). And a private field is, per definition, an implementation detail, and you may make it arbitrarily specific. So it would be feasible to declare it as an
ArrayList - although, strictly speaking, this is not relevant. To phrase it that way: You said
if someone ... changed
list to a
LinkedList, this would be problematic,...
The one who can change the declaration from
private List<T> list = new ArrayList<T>();
private List<T> list = new LinkedList<T>();
can also change the declaration from
private ArrayList<T> list = new ArrayList<T>();
private LinkedList<T> list = new LinkedList<T>();
The only practical way to prevent this would be to add this (important) implementation detail as a comment, e.g.
* 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>();
(This could also be enforced by internally passing the list to a method that expects it to be a
RandomAccess. This was proposed by AlexR, but referring to
public methods. For
private methods, even this won't prevent someone from changing the method signature, if the intention and the reasons for requiring
RandomAccess are not documented).