Java Colección tipo variable para HashSet o otras implementaciones?

Stonr96:

Muchas veces he visto como declaraciones List<String> list = new ArrayList<>();o Set<String> set = new HashSet<>();de los campos en clases. Para mí tiene mucho sentido utilizar las interfaces para los tipos de variables para proporcionar flexibilidad en la aplicación. Los ejemplos anteriores no todavía definir qué tipo de Collections tiene que ser utilizado, respectivamente, que las operaciones están permitidas y cómo debe comportarse en algunos casos (debido a docs).

Consideremos ahora el caso en el que en realidad sólo la funcionalidad de la Collection(o incluso el Iterablese requiere) interfaz para utilizar el campo de la clase y el tipo de Collectionrealidad no importa, o no quiero a overspecify ella. Así que elegir, por ejemplo, HashSetcomo la implementación y declaro el campo Collection<String> collection = new HashSet<>();.

En caso de que el campo luego en realidad ser de tipo Seten este caso? Es este tipo de mala práctica de la declaración, si es así, ¿por qué? O se trata de una buena práctica para especificar el tipo real lo menos posible (y aún así proporcionar a todos los métodos necesarios). La razón por la que pido esto se debe a que casi nunca he visto tal declaración y últimamente me obtener más de una más en la situación en la que sólo debe indicar la funcionalidad de la Collectioninterfaz.

Ejemplo:

// Only need Collection features, but decided to use a LinkedList
private final Collection<Listener> registeredListeners = new LinkedList<>();

public void init() {
    ExampleListener listener = new ExampleListener();
    registerListenerSomewhere(listener);
    registeredListeners.add(listener);
    listener = new ExampleListener();
    registerListenerSomewhere(listener);
    registeredListeners.add(listener);
}

public void reset() {
    for (Listener listener : registeredListeners) {
        unregisterListenerSomewhere(listener);
    }

    registeredListeners.clear();
}
Stuart Marcas:

Debido a que su ejemplo se utiliza un campo privado no importa todo lo que mucho acerca de cómo ocultar el tipo de aplicación. Usted (o quien es el mantenimiento de esta clase) siempre puede ir a buscar a inicializador de campo para ver lo que es.

Dependiendo de cómo se utiliza, sin embargo, podría valer la pena declarar una interfaz más específica para el campo. Declarando que es una Listindica que se permiten duplicados y que un pedido es significativa. Declarando que es una Setindica que los duplicados no están permitidos y que el pedido no es significativo. Puede ser que incluso declarar el campo para tener una clase de implementación particular, si hay algo en él que es significativo. Por ejemplo, declarando que era LinkedHashSetindica que los duplicados no están permitidos, pero ese ordenamiento es significativa.

La elección de si usar una interfaz, y qué interfaz para su uso, se vuelve mucho más significativa si el tipo aparece en la API pública de la clase, y en lo que las restricciones de compatibilidad de esta clase son. Por ejemplo, supongamos que eran un método

public ??? getRegisteredListeners() {
    return ...
}

Ahora la elección del tipo de retorno afecta a otras clases. Si usted puede cambiar todas las personas que llaman, tal vez no es gran cosa, sólo tienes que otros archivos editados. Pero supongamos que la persona que llama es una aplicación que no tiene ningún control sobre. Ahora la elección de la interfaz es crítica, ya que no se puede cambiar sin romper potencialmente las aplicaciones. La regla aquí es por lo general para elegir la interfaz más abstracto que es compatible con las operaciones que se pueden esperar las personas que llaman quieren llevar a cabo.

La mayor parte de la devolución API Java SE Collection. Esto proporciona un alto grado de abstracción de la implementación subyacente, sino que también proporciona la persona que llama un conjunto razonable de las operaciones. La persona que llama puede recorrer en iteración, obtener el tamaño, hacer un cheque contiene, o copiar todos los elementos a otra colección.

Algunas bases de código utilizan Iterablecomo la interfaz más abstracta para volver. Todo lo que hace es permitir que la persona que llama para iterar. A veces esto es todo lo que es necesario, pero podría estar limitando un poco en comparación con Collection.

Otra alternativa es devolver un Stream. Esto es útil si cree que la persona que llama podría querer usar las operaciones de la corriente (tales como filtro, mapa, saber, etc.) en lugar de la iteración o el uso de las operaciones de recogida.

Tenga en cuenta que si decide volver Collectiono Iterable, lo que necesita para asegurarse de que regrese una vista no se puede modificar o hacer una copia defensiva. De lo contrario, las personas que llaman pueden modificar los datos internos de su clase, que probablemente conduciría a errores. (Sí, incluso una Iterablepuede permitir la modificación! Considere la compra de una Iteratory luego llamar al remove()método.) Si devuelve una Stream, no es necesario que preocuparse por eso, ya que no puede utilizar una Streamde modificar la fuente subyacente.

Tenga en cuenta que me di la pregunta sobre la declaración de un campo en una pregunta sobre la declaración de tipo de retorno del método. Existe esta idea de "programa para la interfaz" que está bastante frecuente en Java. En mi opinión no importa mucho para las variables locales (que es por eso que es generalmente muy bien para su uso var), y poco importa para los campos privados, ya que los (casi) por definición afectan sólo a la clase en la que están declaradas. Sin embargo, el "programa para la interfaz" principio es muy importante para la firma de API, por lo que esos casos son donde realmente se necesita pensar acerca de los tipos de interfaz. Campos privados, no tanto.

(Una nota final: hay un caso donde tiene que preocuparse acerca de los tipos de campos privados, y que de cuando se está utilizando un marco de reflexión que manipula los campos privados directamente En ese caso, es necesario pensar en esos campos como. siendo pública - al igual que los tipos de retorno del método - a pesar de que no están declarados public).

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=138174&siteId=1
Recomendado
Clasificación