No soy un súper experto en Java, por lo que no estoy completamente seguro de lo que voy a decir. Aquí están mis pensamientos:
Como Java implementa genéricos por borrado, para cada tipo genérico hay un tipo sin procesar subyacente. Si define un tipo genérico, habrá un tipo sin procesar subyacente que usará Object
por todas partes.
Cuando se instancia un nuevo ArrayList
, sería un error de compilador para inferir el parámetro de tipo de la clase de instancias (ArrayList<String>
en su ejemplo), ya que hay una clase con ese nombre exacto y ningún parámetro de tipo (que es la tipo sin procesar, ArrayList
). También creo que esta es la razón por la cual en java 7 tendrá que agregar <>
a la llamada del constructor para decirle al compilador que deduzca el tipo.
Se podría argumentar que el compilador debe crear una instancia del tipo sin formato solo cuando la clase de definición es el tipo sin formato, pero creo que sería confuso. Creo que el compilador debe inferir a partir de expresiones incompletas que no serían válidas sin un contexto dado, que no es el caso para la declaración new ArrayList()
.
Espero que esto esté claro, y que si me equivoco alguien me puede corregir.
Nota al margen:
Además, ten en cuenta que la clase prima no es el mismo que el tipo usando Object
como parámetro de tipo:
List<String> list = new ArrayList();
es válida, en tanto que
List<String> list = new ArrayList<Object>();
no lo es. En el primer caso, el tipo sin procesar se puede usar como si fuera un tipo genérico, pero en el segundo caso se pregunta por la contravariación que no está disponible (no si no se usan comodines).
¿Existe un propósito al preguntar "¿por qué el lenguaje X no tiene Y"? La respuesta suele ser "porque no fue diseñada para". – skaffman
¡Por qué! ¡Oh por qué! Esa es una de mis mayores quejas sobre la implementación de genéricos en Java. Envolver el constructor en un método de fábrica estático hace que la inferencia de tipo funcione como un amuleto, ¿por qué no con el constructor? –
@skaffman: cierto, pero lo confuso es que la inferencia de tipo existe para los métodos parametrizados, por lo que las reglas y la complejidad de la implementación ya existen. ¡Simplemente no para la instanciación de objetos! –