Should variables always be declared with an interface in Java?

You can often see that variables must be declared using some interface, not an implementation class. For instance:

List<Integer> list = new ArrayList<>(); 

However, let's say I use this list for an algorithm that really depended on O (1) random access from an ArrayList (e.g. Fisher-Yate shuffle). In this case, the key abstraction that ArrayList represents for me is its massive nature, and not just its List nature. In other words, if someone came in and changed the list to LinkedList , that would be problematic even if the code compiled. In this case, is the use of an implementation type declaration considered approved ?, for example:

 ArrayList<Integer> list = new ArrayList<>(); 
+6
source share
2 answers

To emphasize what Oliver Charlworth said in a comment: The most important difference is whether this information is public or not.

From how the question is written, it looks like you are talking about a field (not a method parameter or return value). And a private field, by definition, is an implementation detail, and you can make it arbitrary. Thus, it would be possible to declare it as an ArrayList , although, strictly speaking, it does not matter. To put it this way: you said

if someone ... changed list to LinkedList , that would be problematic ...

Anyone who can change an ad from

 private List<T> list = new ArrayList<T>(); 

to

 private List<T> list = new LinkedList<T>(); 

can also change an ad from

 private ArrayList<T> list = new ArrayList<T>(); 

to

 private LinkedList<T> list = new LinkedList<T>(); 

The only practical way to prevent this is to add this (important) implementation detail as a comment, for example.

 /** * 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 can also be implemented by internally transferring the list to a method that expects it to be RandomAccess . This was suggested by AlexR but referenced to public methods. For private methods, this even won the β€œprevent anyone from changing the method signature if intent and reason for the requirements of RandomAccess not documented).

+3
source

I think the use of interfaces is still very important. You are very special, but there is a way to solve it without using specific classes. There is an interface called RandomAccess . This is a tag interface that does not declare methods, but must be used by developers or List that provide access to randome elements.

So, you can define your own method, which requires a random access list, as shown below:

 public <E, L extends List<E> & RandomAcess>void algorithm(L list); 

You cannot pass a linked list to this method, but an ArrayList will work. As you expect, now you can change the implementation of the list without changing your algorithm. For example, you can use the safe CopyOnWriteArrayList stream, which allows you to handle multithreading without explicit syncrhonized instructions.

+2
source

Source: https://habr.com/ru/post/978899/


All Articles