2009-11-17 17 views

Respuesta

34

Exponen diferentes interfaces y contrato para el método.

La primera declaración debe devolver una colección cuyos elementos tipo es el mismo de la clase argumento. El compilador infiere el tipo de N (si no se especifica). Así que las dos afirmaciones siguientes son válidos cuando se utiliza la primera declaración:

Collection<Integer> c1 = getThatCollection(Integer.class); 
Collection<Double> c2 = getThatCollection(Double.class); 

La segunda declaración no declara la relación entre el argumento de tipo cobro devuelto a la clase de argumento. El compilador asume que no están relacionados, por lo que el cliente tendría que utilizar el tipo devuelto como Collection<? extends Number>, independientemente de lo que el argumento es:

// Invalid statements 
Collection<Integer> c1 = getThatCollection(Integer.class); // invalid 
Collection<Double> c2 = getThatCollection(Double.class); // invalid 
Collection<Number> cN = getThatCollection(Number.class); // invalid 

// Valid statements 
Collection<? extends Number> c3 = getThatCollection(Integer.class); // valid 
Collection<? extends Number> c4 = getThatCollection(Double.class); // valid 
Collection<? extends Number> cNC = getThatCollection(Number.class); // valid 

Recomendación

Si de hecho existe una relación entre la escriba entre el argumento de tipo devuelto y el argumento pasado, es mucho mejor usar la primera declaración. El código del cliente es más limpio como se indicó anteriormente.

Si la relación no existe, entonces es mejor evitar la segunda declaración. Tener un tipo devuelto con un comodín delimitado obliga al cliente a utilizar comodines en todas partes, por lo que el código del cliente se vuelve ruidoso e ilegible. Joshua Bloch enfatiza que debe Avoid Bounded Wildcards in Return Types (diapositiva 23). Si bien los comodines delimitados en los tipos de devolución pueden ser útiles en algunos casos, la fealdad del código resultante debe, en mi humilde opinión, anular el beneficio.

+3

+1 para una explicación clara de las diferencias. Una objeción menor: creo que vas demasiado lejos al suponer que la primera siempre es la mejor opción. Diría que "no hace falta decir" que la mejor opción dependería del contexto. –

+0

@Steve ¡Gracias! Agregué una explicación de por qué se debe evitar la segunda declaración. – notnoop

+0

+1 ¡Respuesta impresionante! – Stephan

-3

En este caso particular, no. sin embargo, la segunda opción es más flexible, ya que le permitiría devolver una colección que contiene elementos de un tipo diferente (aunque también sería un Número) que el tipo que contiene el parámetro de recopilación.

ejemplo concreto:

Collection<? extends Number> getRoot(Class<? extends Number> number){ 
    ArrayList<Integer> result=new ArrayList<Integer>(); 
    result.add(java.util.Math.round(number); 
    return result) 
} 
Cuestiones relacionadas