El operador de diamantes en java 7 permite códigos como el siguiente:
List<String> list = new LinkedList<>();
Sin embargo, en Java 5/6, simplemente puedo escribir:
List<String> list = new LinkedList();
Según tengo entendido, el tipo de borrado es que son exactamente iguales. (El genérico se elimina en tiempo de ejecución de todos modos).
¿Por qué molestarse con el diamante? ¿Qué nueva funcionalidad / tipo de seguridad permite? Si no ofrece ninguna funcionalidad nueva, ¿por qué lo mencionan como una característica? ¿Mi comprensión de este concepto es defectuosa?
java
generics
java-7
diamond-operator
tofarr
fuente
fuente
Respuestas:
El problema con
es que en el lado izquierdo, está utilizando el tipo genérico, mientras
List<String>
que en el lado derecho está utilizando el tipo sin formatoLinkedList
. Los tipos sin formato en Java efectivamente solo existen para la 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 los
LinkedList
que se crearon originalmente antes de tener genéricos, probablemente podría haberlo hecho para que el constructor de un tipo genérico infiera automáticamente sus parámetros de tipo desde la izquierda lado de la tarea, si es posible. Pero no lo hizo, y debe tratar los tipos sin procesar y los 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:Existen genéricos para proporcionar protección en tiempo de compilación contra hacer lo incorrecto. En el ejemplo anterior, el uso del tipo sin formato significa que no obtiene esta protección y obtendrá un error en tiempo de ejecución. Es por eso que no debes usar tipos sin procesar.
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 volver a escribir esos parámetros. Le permite mantener la seguridad de los genéricos con casi el mismo esfuerzo que usar el tipo sin procesar.
Creo que la clave para entender es que los tipos sin formato (sin
<>
) no pueden tratarse de la misma manera que los tipos genéricos. Cuando declara un tipo sin procesar, no obtiene ninguno de los beneficios y la verificació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 deCollection
s!fuente
-compatibility
interruptor del compilador mientras que si está ausentejavac
, prohibirá todos los tipos sin formato y solo aplicará tipos estrictamente genéricos? Esto hará que nuestros códigos sean menos detallados tal como están.List<String> strings = new List<>()
está bien, pero si defineprivate List<String> my list;
, y luego a la mitad de la página con la que crea una instanciamy_list = new List<>()
, ¡no está bien! ¿Qué contiene mi lista nuevamente? Oh, déjame buscar la definición. De repente, el beneficio del atajo de diamante se despide.my_list = getTheList()
:? Hay varias formas mejores de lidiar con este tipo de problemas: 1. use un IDE que le muestre tipos de variables al pasar el mouse. 2. use nombres de variables más significativos, comoprivate List<String> strings
3. no divida la declaración y la inicialización de variables a menos que realmente tenga que hacerlo.Tu comprensión es ligeramente defectuosa. El operador de diamante es una buena característica, ya que no tiene que repetirlo. Tiene sentido definir el tipo una vez cuando declara el tipo, pero simplemente no tiene sentido definirlo nuevamente en el lado derecho. El principio SECO.
Ahora para explicar toda la confusión sobre la definición de tipos. Tiene razón en que el tipo se elimina en tiempo de ejecución, pero una vez que desea recuperar algo de una Lista con definición de tipo, lo recupera como el tipo que ha definido al declarar la lista; de lo contrario, perdería todas las características específicas y solo tendría el Características del objeto, excepto cuando convierte el objeto recuperado a su tipo original, que a veces puede ser muy complicado y dar lugar a una ClassCastException.
El uso
List<String> list = new LinkedList()
le proporcionará advertencias de tipo crudo.fuente
List<String> list = new LinkedList()
Es el código correcto. Tú sabes esto y yo también lo sé. Y la pregunta (según tengo entendido) es: ¿por qué solo el compilador de Java no entiende que este código es bastante seguro?List<String> list = new LinkedList()
es el código correcto. Claro, ¡sería bueno si lo fuera! Y probablemente podría haber sido si Java tuvo genéricos desde el principio y no tuvo que lidiar con la compatibilidad con versiones anteriores de tipos genéricos que solían ser no genéricos, pero lo tiene.<?>
si se conecta al código heredado) y el operador de diamante inútil no debería existir.Esta línea provoca la advertencia [sin marcar]:
Entonces, la pregunta se transforma: ¿por qué la advertencia [sin marcar] no se suprime automáticamente solo para el caso cuando se crea una nueva colección?
Creo que sería una tarea mucho más difícil que agregar
<>
funciones.UPD : También creo que sería un desastre si legalmente se usaran tipos sin formato "solo por algunas cosas".
fuente
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é?
En mi humilde opinión, tener una forma clara y simple de marcar una fuente como Java 7 sería más útil que inventar cosas tan extrañas. En un código tan marcado, los tipos sin procesar podrían prohibirse sin perder nada.
Por cierto, no creo que deba hacerse con un interruptor de compilación. La versión Java de un archivo de programa es un atributo del archivo, no tiene ninguna opción. Usando algo tan trivial como
podría dejarlo claro (puede preferir algo más sofisticado que incluya una o más palabras clave elegantes). 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 (múltiples clases no públicas no anidadas en un solo archivo o en absoluto) sin perder ninguna compatibilidad.
fuente
new ArrayList(anotherList)
ynew ArrayList<>(anotherList)
(especialmente si se le está asignandoList<String>
yanotherList
es aList<Integer>
)?new @RawType List()
? Esa es la sintaxis de Java 8 válida y las anotaciones de tipo permiten usarlo en todos los lugares donde sea necesario, por ejemplo@RawType List = (@RawType List) genericMethod();
. Teniendo en cuenta que los tipos sin formato actualmente crean una advertencia de compilación a menos que@SuppressWarnings
se haya colocado un apropiado ,@RawType
sería un reemplazo razonable y no se necesita una sintaxis más sutil.Cuando escribe
List<String> list = new LinkedList();
, el compilador genera 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 de diamante le permite hacerlo de manera conveniente sin repeticiones innecesarias.
fuente
Todo lo dicho en las otras respuestas son válidas, pero los casos de uso no son completamente válidos en mi humilde opinión. Si se comprueba la guayaba y especialmente las cosas relacionadas con las colecciones, lo mismo se ha hecho con métodos estáticos. Por ejemplo, Lists.newArrayList () que te permite escribir
o con importación estática
La guayaba tiene otras características muy poderosas como esta y en realidad no puedo pensar en muchos usos para el <>.
Hubiera sido más útil si optaran por hacer que el comportamiento del operador de diamante sea el predeterminado, es decir, el tipo se deduce del lado izquierdo de la expresión o si el tipo del lado izquierdo se deduce del lado derecho. Esto último es lo que sucede en Scala.
fuente
El objetivo para el operador de diamantes es simplemente reducir la tipificación de código al declarar tipos genéricos. No tiene ningún efecto sobre el tiempo de ejecución.
La única diferencia si especifica en Java 5 y 6,
es que usted tiene que especificar
@SuppressWarnings("unchecked")
lalist
(de lo contrario obtendrá una advertencia fundido sin marcar). 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.fuente