2009-08-19 22 views
9

¿Cuál es la ventaja de tener un constructor genérico para una clase no genérica? especificación de Java permite el siguiente:Ventaja de constructores genéricos

class NonGeneric { 
    <T> NonGeneric() { } 
    ... 
    NonGeneric ref = new <String> NonGeneric(); 
} 

¿Se puede llegar a un ejemplo realista de cuando se aumenta la typesafety de la clase? ¿Cómo sería mejor que usar Generic en primer lugar?

Entiendo que los diseñadores de Java querían que los constructores fueran más consistentes con los métodos. Dado que los constructores pueden tener efectos secundarios, constructores genéricos pueden utilizar genéricos para mutar algunos parámetros cuyas referencias no se conservan, como en

<T> NonGeneric(T obj, List<T> list) { 
    list.add(obj); 
    // Don't hold a reference to list 
} 

Respuesta

4

El único uso que se me ocurre sería si el constructor necesitaba utilizar un objeto genérico mientras se estaba ejecutando, pero no almacenó ese objeto una vez que se completó.

Por ejemplo:

<T> NonGeneric(T[] blank, List<T> list) { 
    // Sort that list 
    T[] array = list.toArray(blank); 
    Arrays.sort(array); 

    // Pull out the values as strings 
    this.list = new ArrayList<String>(array.length); 
    for (T value : array) { 
     this.list.add(value.toString()); 
    } 
} 

Lo más probable es sólo algo que los diseñadores del lenguaje decidieron hacerlo por si acaso alguien lo quería, ya que no había ninguna razón para evitar que la gente lo hace.

+0

Sí, permite que los métodos genéricos sean reemplazados por constructores (¿pero por qué querrías?). Nunca he visto uno en la naturaleza. Por mi dinero, es una complicación que el lenguaje podría haber prescindido (como C# lo hizo más tarde cuando presentó su versión de los genéricos de Java). –

0

Sí, estaba pensando en lo mismo unas cuantas veces.

Hipotéticamente (hay xx razones por las que no es así) sería bueno si los constructores genéricos pudieran definir el tipo genérico formal para toda la clase (como lo hace la declaración de clase genérica) ... Es decir, si se definen constructor genérico dejaría que tiene campos genéricos de esa clase ...

Por ejemplo si se quería evitar la generalización:

EntityRequestCallback extends RequestCallback 

pero quería que el RequestCallback a ser genérica RequestCallback<E extends Entity>, no se podía hacer eso porque solo dos tipos de solicitud PUT/POST usan Entity. Solo los constructores para las solicitudes PUT/POST contienen el parámetro Entity.

public class RequestCallback { 

     /** GET/DELETE requests */ 
    public RequestCallback(String gttUrl, HttpMethod method,) { 
     this.gttUrl = gttUrl; 
       this.method = method; 
    } 

     /** PUT/POST requests */ 
    public RequestCallback(String gttUrl, HttpMethod method, Entity entity) { 
     this.gttUrl = gttUrl; 
       this.method = method; 
     this.entity = entity; 
    } 
} 

Pero la clase no puede ser genérico, ya que sería la creación de RequestCallback para una solicitud que no tiene una entidad, lo que significaría que tendría una instancia

new RequestCallback(); //without specifying generic parameter - worse than nothing 

Así que la única manera posible aquí se ofrecen generalización:

EntityRequestCallback<E extends Entry> extends RequestCallback 

Para que pueda tener campos genéricos:

public E entity; 

En este ejemplo en particular, la generalización es la elección correcta de todos modos, pero hay casos en que la generalización no lo sería.