Saltar al contenido

¿Por qué no puedo usar un argumento de tipo en un parámetro de tipo con múltiples límites?

Después de de nuestra prolongada recopilación de datos dimos con la solución esta pregunta que suelen tener muchos de nuestros lectores. Te ofrecemos la respuesta y nuestro objetivo es servirte de mucha ayuda.

Solución:

Tampoco estoy seguro de por qué la restricción está ahí. Podría intentar enviar un correo electrónico amistoso a los diseñadores de Java 5 Generics (principalmente Gilad Bracha y Neal Gafter).

Supongo que querían admitir solo un mínimo absoluto de tipos de intersección (que es lo que esencialmente son los límites múltiples), para que el lenguaje no sea más complejo de lo necesario. Una intersección no se puede utilizar como una anotación de tipo; un programador solo puede expresar una intersección cuando aparece como el límite superior de una variable de tipo.

¿Y por qué se apoyó este caso? La respuesta es que los límites múltiples le permiten controlar el borrado, lo que permite mantener la compatibilidad binaria al generar clases existentes. Como se explica en la sección 17.4 del libro de Naftalin y Wadler, un max El método lógicamente tendría la siguiente firma:

public static > T max(Collection coll)

Sin embargo, esto se borra a:

public static Comparable max(Collection coll)

Que no coincide con la firma histórica de max, y hace que los clientes antiguos se rompan. Con múltiples límites, solo el límite más a la izquierda se considera para el borrado, por lo que si max se da la siguiente firma:

public static > T max(Collection coll)

Entonces el borrado de su firma se convierte en:

public static Object max(Collection coll)

Que es igual a la firma de max antes de los genéricos.

Parece plausible que los diseñadores de Java solo se preocuparon por este caso simple y restringieron otros usos (más avanzados) de los tipos de intersección porque simplemente no estaban seguros de la complejidad que podría traer. Por lo tanto, el motivo de esta decisión de diseño no tiene por qué ser un posible problema de seguridad (como sugiere la pregunta).

Más discusión sobre los tipos de intersección y las restricciones de los genéricos en un próximo documento de OOPSLA.

Dos posibles razones para prohibir esto:

  1. Complejidad. JDK-4899305 sugiere que un límite que contenga un parámetro de tipo más tipos parametrizados adicionales permitiría tipos mutuamente recursivos aún más complicados que los que ya existen. En resumen, la respuesta de Bruno.

  2. La posibilidad de especificar tipos ilegales. Específicamente, extender una interfaz genérica dos veces con diferentes parámetros. No puedo encontrar un ejemplo no artificial, pero:

    /** Contains a Comparator that also implements the given type T. */
    class StringComparatorHolder> 
      private final C comparator;
      // ...
    
     
    void foo(StringComparatorHolder, ?> holder)  ... 

Ahora holder.comparator es un Comparator y un Comparator. No me queda claro exactamente cuántos problemas le causaría esto al compilador, pero claramente no es bueno. Supongamos en particular que Comparator tenía un método como este:

void sort(List list);

Nuestro Comparator / Comparator híbrido ahora tiene dos métodos con el mismo borrado:

void sort(List list);
void sort(List list);

Es por este tipo de razones que no puede especificar un tipo de este tipo directamente:

 & Comparator> void bar()  ... 
java.util.Comparator cannot be inherited with different arguments:
     and 

Ya que > le permite hacer lo mismo indirectamente, también está descartado.

Aquí hay otra cita de JLS:

La forma de un límite está restringida (solo el primer elemento puede ser una variable de clase o tipo, y solo puede aparecer una variable de tipo en el límite) a impedir que surjan ciertas situaciones incómodas.

¿Qué son exactamente esas situaciones incómodas? No lo sé.

Si guardas algún reparo y capacidad de enriquecer nuestro enunciado te invitamos ejecutar un paráfrasis y con placer lo observaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *