2011-02-01 18 views
5

Ha habido un par de veces cuando me he sentido la necesidad de hacer algo como lo siguiente:Java delimitada limitaciones genéricas en los campos

private <T extends Type> Map<GenericClass1<T>,GenericClass2<T>> map; 

... o algo por el estilo. Esencialmente, usando un límite idéntico en los dos argumentos para el mapa. (Este no es un ejemplo real, solo muestra la idea.)

Sé que esto (lamentablemente) no es posible y que solo está disponible en las definiciones de clases y las firmas de métodos. Mi pregunta, sin embargo, es ¿por qué no está disponible en los campos? ¿Es puramente una elección de diseño o hay alguna razón técnica detrás de la que me estoy perdiendo? He tenido una idea y no puedo ver por qué esto no debería ser posible desde una perspectiva técnica, por lo que puedo ver que todo está ahí para que el compilador lo resuelva correctamente y no se requiera ninguna información genérica en el tiempo de ejecución .

Respuesta

1

<T> significa UNA clase, no una clase. Cuando se instancia su objeto, T está vinculado a esta clase ONE.

Está tratando de poner dos objetos con diferentes interfaces (utilizados de forma diferente porque toman/devuelven tipos diferentes) en el mismo contenedor. Esto es un error porque cuando los sacas del contenedor (el mapa) no sabes qué fue lo que pusiste.

Espero que esta es la respuesta que estabas buscando.

Editar: Dicho esto, puede tener un contenedor que contenga miembros basados ​​en su clase, para crear automáticamente un nuevo mapa para CADA tipo de T. Entonces necesitaría saber qué era T para poder acceder a él. En general, si ya no desea la información del tipo, deséchela. Si lo hace, colocarlo en el mismo contenedor como algo de otro tipo lo arrojará de todos modos por todos los motivos prácticos.

+0

@ "no se requiere ninguna información genérica en el tiempo de ejecución", si el compilador le permite hacer cosas en función de lo que fue posible en el tiempo de ejecución, entonces su idioma ya no se tipea. Escribir es las restricciones. – mncl

+0

Gracias por la respuesta. Veo lo que dices, pero donde pude ver que esto es útil es que si conoces el parámetro genérico de la clave, puedes garantizar que obtendrás un objeto con el mismo límite genérico exacto. – berry120

+0

Si conoce el tipo de objeto, ejecútelo. pero si alguna vez lo haces, si (x instancia de y) lo más probable es que lo estés haciendo mal. Guarde el tipo en su lugar. – mncl

0

Puede utilizar ? de la siguiente manera:

private List<? extends List> l = new ArrayList<List>();

espero que esto ayude.

+0

Gracias por la respuesta, pero eso no es lo que busco: sé que puedo usar comodines básicos de esa manera, pero quiero capturar exactamente el mismo límite (en la pregunta, T) a través de múltiples parámetros genéricos. Podría usar "? Extends Type" dos veces, pero eso no garantizará el mismo límite, podrían ser dos clases diferentes que amplíen Type. – berry120

1

Supongamos que quiere crear una instancia de su variable map. Teóricamente tendrá que escribir algo como esto:

map = new HashMap<GenericClass1<String>,GenericClass2<String>>(); 

Ok. Pero ahora lo que no tiene sentido para mí más ¿Qué argumentos aceptarán o devolverán los métodos put o get? T? Uh ... ¿qué es T? GenericClass1|2<String>? De nuevo, no tiene sentido, ¿verdad? Después de todo, no veo String en la declaración map. Así que supongo que no hay una instanciación y uso realmente correctos de esta variable genérica.

¡Salud!

1

Oh, cómo he anhelado algo como:

private <T> Map<Class<T>, T> instanceCache; 

public <T> T getInstanceOf(Class<T> clazz) { 
    return instanceCache.get(clazz); 
} 

Pero como usted ha mencionado, es completamente imposible en Java. La declaración de método anterior está bien, pero no hay forma de declarar la variable de modo que no haya un molde en el método. Simplemente agregue esto a la creciente lista de cosas que odia sobre los genéricos y continúe.

Cuestiones relacionadas