java 10 var
¿Cómo se unen "var" y tipos sin procesar? (2)
Me encontré con una respuesta que sugiere utilizar ...
Ignoraría esa respuesta , porque como usted señala, usa tipos brutos y tipos de list
como específicamente ArrayList
. (Actualización: el respondedor editó su respuesta para agregar un tipo de elemento). En cambio:
List<AppropriateElementType> list = new ArrayList<>();
De acuerdo con la segunda respuesta que vinculó , var
hará que el compilador deduzca un tipo de elemento desde el lado derecho si incluye <>
, seleccionando el tipo más específico que pueda. In var list = new ArrayList<>();
Sin embargo, eso sería ArrayList<Object>
, porque no tiene nada más específico que pueda elegir.
Pero , esto:
var list = new ArrayList();
... sin el <>
, está utilizando un tipo sin ArrayList
( ArrayList
), no un tipo parametrizado con Object
como el parámetro ( ArrayList<Object>
), que es diferente.
Si el uso de la list
está suficientemente contenido (unas pocas líneas en un método), haberlo escrito ArrayList<X>
lugar de List<X>
puede ser aceptable (depende de su estilo de codificación), en cuyo caso:
var list = new ArrayList<AppropriateElementType>();
Pero en general prefiero codificar a la interfaz en lugar de a la clase concreta, incluso con los locales. Dicho esto, con los locales, es menos importante que con los miembros de la instancia, y var
es conveniente.
Me encontré con una answer que sugiere utilizar
var list = new ArrayList();
Me sorprendió encontrar un tipo sin formato aquí, y simplemente me pregunto: ¿utiliza var
<>
"automáticamente?
(Mientras tanto, la respuesta se cambió para usar <String>
, pero todavía siento curiosidad por los "principios" aquí)
Vi otras preguntas como this , pero todas usan el operador de diamante:
var list = new ArrayList<>();
Ahora simplemente me pregunto: ¿ var
cambia la forma en que deberíamos (no) usar tipos en bruto? ¿O es esa sugerencia de dejar de lado <>
simplemente una mala práctica?
Es legal usar tanto var
como diamond
, pero el tipo inferido cambiará:
var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>
Para su inferencia, el diamond
puede usar el tipo de objetivo (típicamente, el lado izquierdo de una declaración) o los tipos de argumentos de constructor. Si ninguno de los dos está presente, recurre al tipo más amplio aplicable, que a menudo es el Object
1 .
Tanto diamond
métodos de diamond
como con métodos genéricos, la información de tipo adicional puede ser proporcionada por argumentos reales al constructor o método, lo que permite inferir el tipo deseado 1 :
var list = List.of(BigInteger.ZERO); // OK: infers as List<BigInteger>
var list = new ArrayList<String>( ); // OK: infers as ArrayList<String>
En vista de lo anterior, no recomiendo hacer lo siguiente (porque obtendrá el tipo ArrayList
procesar):
var list = new ArrayList(); // DANGEROUS: infers as ArrayList
Conclusión:
- No utilice tipos brutos independientemente de la presencia o ausencia de
var
. - Asegúrese de que los argumentos de método o constructor proporcionen suficiente información de tipo para que el tipo inferido coincida con su intención. De lo contrario, evite usar ambas
var
condiamond
1 .
1 - Directrices de estilo para la inferencia de tipo de variable local: G6. Tenga cuidado al usar var con diamante o métodos genéricos.