sencillo programacion operador objetos lista genericos generica ejemplos diamond java generics java-7 diamond-operator

operador - programacion en java ejemplos



¿Cuál es el punto del operador de diamante en Java 7? (7)

Cuando escribe List<String> list = new LinkedList(); , el compilador produce una advertencia "sin marcar". Puede ignorarlo, pero si solía ignorar estas advertencias, también puede pasar por alto una advertencia que le notifica sobre un problema de seguridad de tipo real.

Por lo tanto, es mejor escribir un código que no genere advertencias adicionales, y el operador Diamond le permite hacerlo de manera conveniente sin repeticiones innecesarias.

El operador de diamante en java 7 permite código como el siguiente:

List<String> list = new LinkedList<>();

Sin embargo, en Java 5/6, simplemente puedo escribir:

List<String> list = new LinkedList();

Mi comprensión de la eliminación de tipos es que estos son exactamente los mismos. (El genérico se elimina en el tiempo de ejecución de todos modos).

¿Por qué molestarse con el diamante? ¿Qué nueva funcionalidad / seguridad de tipo permite? Si no produce ninguna funcionalidad nueva, ¿por qué la mencionan como una característica? ¿Mi comprensión de este concepto es defectuosa?


El problema con

List<String> list = new LinkedList();

es que en el lado izquierdo, está utilizando la List<String> genérica de tipos List<String> que en el lado derecho está utilizando la lista LinkedList tipo sin LinkedList . Los tipos sin procesar en Java solo existen efectivamente por compatibilidad con el código pre-genérico y nunca deben usarse en código nuevo a menos que sea absolutamente necesario.

Ahora, si Java tenía genéricos desde el principio y no tenía tipos, como LinkedList , que se crearon originalmente antes de tener genéricos, probablemente podría haberlo hecho para que el constructor para un tipo genérico infiera automáticamente sus parámetros de tipo del lado izquierdo de la tarea si es posible. Pero no fue así, y debe tratar tipos crudos y tipos genéricos de manera diferente para la compatibilidad con versiones anteriores. Eso hace que tengan que hacer una forma ligeramente diferente , pero igualmente conveniente, de declarar una nueva instancia de un objeto genérico sin tener que repetir sus parámetros de tipo ... el operador de diamante.

En cuanto a su ejemplo original de List<String> list = new LinkedList() , el compilador genera una advertencia para esa asignación porque debe hacerlo. Considera esto:

List<String> strings = ... // some list that contains some strings // Totally legal since you used the raw type and lost all type checking! List<Integer> integers = new LinkedList(strings);

Los genéricos existen para proporcionar protección en tiempo de compilación contra hacer algo incorrecto. En el ejemplo anterior, usar el tipo raw significa que no obtiene esta protección y obtendrá un error en tiempo de ejecución. Esta es la razón por la que no debes usar tipos crudos.

// Not legal since the right side is actually generic! List<Integer> integers = new LinkedList<>(strings);

Sin embargo, el operador de diamante permite que el lado derecho de la asignación se defina como una instancia genérica verdadera con los mismos parámetros de tipo que el lado izquierdo ... sin tener que escribir esos parámetros nuevamente. Le permite mantener la seguridad de los genéricos con casi el mismo esfuerzo que con el tipo sin procesar.

Creo que la clave para comprender es que los tipos sin formato (sin <> ) no se pueden tratar de la misma manera que los tipos genéricos. Cuando declara un tipo sin procesar, no obtiene ninguno de los beneficios y la comprobación de tipos de genéricos. También debe tener en cuenta que los genéricos son una parte de propósito general del lenguaje Java ... ¡no solo se aplican a los constructores sin argumentos de Collection s!


El punto para el operador de diamante es simplemente reducir la escritura del código al declarar tipos genéricos. No tiene ningún efecto en el tiempo de ejecución de ningún tipo.

La única diferencia si especifica en Java 5 y 6,

List<String> list = new ArrayList();

es que tiene que especificar @SuppressWarnings("unchecked") a la list (de lo contrario obtendrá una advertencia de @SuppressWarnings("unchecked") ). Tengo entendido que el operador de diamantes está tratando de facilitar el desarrollo. No tiene nada que ver con la ejecución de genéricos en tiempo de ejecución.


En teoría, el operador de diamante le permite escribir código más compacto (y legible) guardando argumentos de tipo repetido. En la práctica, son solo dos caracteres confusos más que no te dan nada. ¿Por qué?

  1. Ningún programador sano usa tipos brutos en código nuevo. Por lo tanto, el compilador podría simplemente asumir que al escribir argumentos de tipo no desea inferirlos.
  2. El operador de diamante no proporciona información de tipo, simplemente dice que el compilador "estará bien". Así que al omitirlo no puedes hacer daño. En cualquier lugar donde el operador de diamantes sea legal, el compilador podría "inferirlo".

En mi humilde opinión, tener una forma clara y sencilla de marcar una fuente como Java 7 sería más útil que inventar cosas tan extrañas. En el código marcado, los tipos en bruto podrían prohibirse sin perder nada.

Por cierto, no creo que deba hacerse usando un modificador de compilación. La versión de Java de un archivo de programa es un atributo del archivo, sin ninguna opción. Usando algo tan trivial como

package 7 com.example;

podría dejarlo claro (es posible que prefiera algo más sofisticado que incluya una o más palabras clave de fantasía). Incluso permitiría compilar fuentes escritas para diferentes versiones de Java juntas sin ningún problema. Permitiría introducir nuevas palabras clave (por ejemplo, "módulo") o eliminar algunas características obsoletas (varias clases no públicas no anidadas en un solo archivo o lo que sea) sin perder ninguna compatibilidad.


Esta línea provoca la advertencia [sin marcar]:

List<String> list = new LinkedList();

Entonces, la pregunta se transforma: ¿por qué la advertencia [no seleccionada] no se suprime automáticamente solo en el caso de que se cree una nueva colección?

Creo que sería una tarea mucho más difícil que agregar la función <> .

UPD : También creo que habría un desastre si fuera legalmente usar tipos en bruto "solo para unas pocas cosas".


Su comprensión es ligeramente defectuosa. El operador de diamante es una buena característica ya que no tienes que repetirte. Tiene sentido definir el tipo una vez cuando declara el tipo, pero simplemente no tiene sentido definirlo de nuevo en el lado derecho. El principio DRY.

Ahora para explicar todo el fuzz sobre la definición de tipos. Tiene razón en que el tipo se elimine en el tiempo de ejecución, pero una vez que quiera recuperar algo de una Lista con definición de tipo, lo recupera como el tipo que definió al declarar la lista; de lo contrario, perdería todas las características específicas y tendría solo el Las características del objeto, excepto cuando se convierte el objeto recuperado a su tipo original, que a veces puede ser muy difícil y dar lugar a una excepción ClassCastException.

Usando List<String> list = new LinkedList() obtendrá advertencias de tipo de letra.


Todo lo dicho en las otras respuestas es válido, pero los casos de uso no son completamente válidos en mi humilde opinión. Si uno comprueba Guava y especialmente las cosas relacionadas con las colecciones, lo mismo se ha hecho con métodos estáticos. Ej. Lists.newArrayList() que te permite escribir

List<String> names = Lists.newArrayList();

o con importación estática

import static com.google.common.collect.Lists.*; ... List<String> names = newArrayList(); List<String> names = newArrayList("one", "two", "three");

La guayaba tiene otras características muy poderosas como esta y en realidad no puedo pensar en muchos usos para la <>.

Habría sido más útil si hubieran optado por hacer que el comportamiento del operador de diamante fuera el predeterminado, es decir, el tipo se inferirá desde el lado izquierdo de la expresión o si el tipo del lado izquierdo se inferiera desde el lado derecho. Lo último es lo que pasa en scala.