¿Por qué debería preferirse la interfaz para una clase Java?

PMD reportaría una violación por:

ArrayList list = new ArrayList(); 

La infracción fue “Evitar el uso de tipos de implementación como ‘ArrayList’; en su lugar, usar la interfaz”.

La siguiente línea corregirá la violación:

 List list = new ArrayList(); 

¿Por qué debería usarse el último con List lugar de ArrayList ?

El uso de interfaces sobre tipos concretos es la clave para una buena encapsulación y para acoplar libremente su código.

Incluso es una buena idea seguir esta práctica al escribir tus propias API. Si lo hace, más adelante descubrirá que es más fácil agregar pruebas unitarias a su código (usando técnicas de burla), y cambiar la implementación subyacente si es necesario en el futuro.

Aquí hay un buen artículo sobre el tema.

¡Espero eso ayude!

Esto se prefiere porque desacopla su código de la implementación de la lista. El uso de la interfaz le permite cambiar fácilmente la implementación, ArrayList en este caso, a otra implementación de la lista sin cambiar el rest del código, siempre que solo use los métodos definidos en la Lista.

En general, estoy de acuerdo en que la interfaz de desacoplamiento de la implementación es una buena cosa y hará que su código sea más fácil de mantener.

Sin embargo, hay excepciones que debes tener en cuenta. El acceso a objetos a través de interfaces agrega una capa adicional de direccionamiento indirecto que hará que su código sea más lento.

Para mayor interés, realicé un experimento que generó diez mil millones de accesos secuenciales a una ArrayList de 1 millón de longitud. En mi MacBook de 2.4Ghz, el acceso a ArrayList a través de una interfaz de lista tomó 2,10 segundos en promedio, cuando se declaró de tipo ArrayList tomó en promedio 1,67 segundos.

Si está trabajando con listas grandes, en el interior de un bucle interno o con una función llamada frecuentemente, esto es algo que debe tenerse en cuenta.

ArrayList y LinkedList son dos implementaciones de una lista, que es una colección ordenada de elementos. En lo que respecta a la lógica, no importa si utiliza una ArrayList o una LinkedList, por lo que no debe restringir el tipo para que sea eso.

Esto contrasta con, por ejemplo, Colección y Lista, que son cosas diferentes (la lista implica ordenar, la colección no).

¿Por qué debería usarse el último con List en lugar de ArrayList?

Es una buena práctica: Progtwig de interfaz en lugar de implementación

Al reemplazar ArrayList con List , puede cambiar la implementación de la List en el futuro como se muestra a continuación, dependiendo de su caso de uso comercial.

 List list = new LinkedList(); /* Doubly-linked list implementation of the List and Deque interfaces. Implements all optional list operations, and permits all elements (including null).*/ 

O

 List list = new CopyOnWriteArrayList(); /* 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.*/ 

O

 List list = new Stack(); /* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/ 

O

alguna otra implementación específica de la List .

List interfaz de la List define el contrato y la implementación específica de la List se puede cambiar. De esta manera, la interfaz y la implementación están ligeramente acopladas.

Pregunta SE relacionada:

¿Qué significa “progtwigr en una interfaz”?

Incluso para variables locales, el uso de la interfaz sobre la clase concreta ayuda. Puede terminar llamando a un método que está fuera de la interfaz y luego es difícil cambiar la implementación de la Lista si es necesario. Además, es mejor usar la clase o interfaz menos específica en una statement. Si el orden de los elementos no tiene importancia, use una Colección en lugar de una Lista. Eso le da a su código la máxima flexibilidad.

Las propiedades de sus clases / interfaces se deben exponer a través de las interfaces, ya que le da a sus clases un contrato de comportamiento para usar, independientemente de la implementación.

Sin embargo…

En las declaraciones de variables locales, tiene poco sentido hacer esto:

 public void someMethod() { List theList = new ArrayList(); //do stuff with the list } 

Si es una variable local, solo usa el tipo. Todavía es implícitamente upcastable a su interfaz apropiada, y sus métodos deberían aceptar los tipos de interfaz para sus argumentos, pero para las variables locales, tiene mucho sentido usar el tipo de implementación como contenedor, en caso de que necesite la implementación. funcionalidad específica.

En general, para su línea de código no tiene sentido molestarse con las interfaces. Pero, si hablamos de API, hay una buena razón. Tengo una clase pequeña

 class Counter { static int sizeOf(List< ?> items) { return items.size(); } } 

En este caso, se requiere el uso de la interfaz. Porque quiero contar el tamaño de cada implementación posible , incluida mi propia costumbre. class MyList extends AbstractList...

Spring framework aplica el concepto de interfaces muy bien – http://www.springframework.org/

Spring proporciona la implementación a una clase concreta a través del archivo de configuración, por lo que la clase concreta no necesita saber nada sobre la implementación.

Study of Spring ejemplifica las ventajas de la progtwigción basada en interfaz en Java.