Card 04/ 08
Declaring the Interface Type, Not the Class
List on the left, ArrayList only after new, so the implementation can change in one place.
A variable or parameter's declared type says what the code needs, and the class after new says how it is provided. Declaring the interface (List) and creating the class (ArrayList) keeps the choice of implementation a local decision instead of something every caller depends on.
A method that takes an ArrayList now needs to accept a list built somewhere else, and the somewhere else produces a LinkedList. The change is one word, in eleven files:
List<String> refs = new ArrayList<>();
void report(List<String> refs) { }List says "something ordered that I can walk", which is true of every list ever written. ArrayList says "this exact class", which is more than you needed and less than you could accept.
| Declared as | Accepts | Changing the implementation |
|---|---|---|
List<String> | Any list | One word, in one place |
ArrayList<String> | Only ArrayList and its subclasses | Every declaration and every signature |
It matters most at method boundaries. A parameter typed ArrayList refuses List.of(...), Arrays.asList(...), and whatever a library hands you, none of which was a decision anyone made on purpose.
So name the interface everywhere except immediately after new. It costs nothing, and the day a LinkedList or an unmodifiable list turns up, the only line that changes is the one that creates it. The same applies to return types: returning List lets you change the implementation without touching callers.
← → move through sections and cards