¿Qué es una conversión de captura en Java y alguien puede darme ejemplos?

4 minutos de lectura

avatar de usuario
Juan Asínptoth

He notado que JLS habla de 5.1.10 Conversión de capturapero no entiendo lo que son.

¿Alguien me los puede explicar/dar ejemplos?

  • ¿No hay ejemplos más que en la discusión inmediatamente a continuación?

    – Tom Hawtin – tachuela

    13 de diciembre de 2010 a las 17:57

  • Eso es cierto, proporcionan un ejemplo, pero a partir de él, no pude entender qué son las conversiones de captura. ¿Entendiste el ejemplo? Si es así, me podrían explicar cuáles son. Gracias.

    – John Asintoth

    13 de diciembre de 2010 a las 18:14

  • Métodos auxiliares y de captura de comodines docs.oracle.com/javase/tutorial/java/generics/capture.html Básicamente: dada una List<?> iel método auxiliar convierte el comodín capturado en un tipo conocido <T> en el método auxiliar, de modo que ahora puede invocar un método set() de List<T> l que requiere un tipo conocido.

    – Nor.Z

    26 de enero a las 10:34

avatar de usuario
buhake sindi

La conversión de captura fue diseñada para hacer comodines (en genéricos), ? útil.

Supongamos que tenemos la siguiente clase:

public interface Test<T> {
    public void shout(T whatever);
    public T repeatPreviousShout();

}

y en algún lugar de nuestro código tenemos,

public static void instantTest(Test<?> test) {
    System.out.println(test.repeatPreviousShout());
}

Porque test no es un crudo Test y desde repeatPreviousShout() en “retrospectiva” devuelve un ?el compilador sabe que hay un T que sirve como parámetro de tipo para Test. Esta T es para algunos desconocidos T por lo que el compilador borra el tipo desconocido (para el comodín, lo reemplaza con Object)., por eso repeatPreviousShout() devuelve un Object.

Pero si tuviéramos,

public static void instantTest2(Test<?> test) {
    test.shout(test.repeatPreviousShout());
}

El compilador nos daría un error de algo así como Test<capture#xxx of ?> cannot be applied (donde xxx es un número, por ejemplo 337).

Esto se debe a que el compilador intenta realizar la comprobación de seguridad de tipo en shout() pero como recibió un comodín, no sabe qué T representa, por lo tanto, crea un marcador de posición llamado captura de.

Desde aquí (Teoría y práctica de Java: Enloquecer con los genéricos, Parte 1)dice claramente:

La conversión de captura es lo que permite que el compilador fabrique un nombre de tipo de marcador de posición para el comodín capturado, de modo que la inferencia de tipo pueda inferir que es ese tipo.

Espero que esto te ayude.

  • Un ejemplo adicional: stackoverflow.com/questions/4449611/…

    – John Asintoth

    18 de diciembre de 2010 a las 4:50


  • @John, si lee el artículo (enlace proporcionado arriba de IBMWorks), verá que el ejemplo que dio proviene de allí.

    – Buhake Sindi

    18 de diciembre de 2010 a las 7:02

avatar de usuario
irreputable

Un tipo parametrizado que involucra argumentos de tipo comodín es realmente un tipo de unión. Por ejemplo

List<? extends Number> = Union{ List<S> | S <: Number }

En 2 casos, en lugar de usar List<? extends Number>Java usa la versión capturada List<S>donde S es una variable de tipo recién creada con límite superior Number.

(1) http://java.sun.com/docs/books/jls/tercera_edición/html/expresiones.html

Restringir el tipo de una expresión. Si el tipo de una expresión es List<? extends Number>sabemos con certeza que el tipo de tiempo de ejecución del objeto es en realidad un List<S> para algunos concretos tipo S (S <: Number>). Entonces el compilador usa List<S> en su lugar, para realizar un análisis de tipo más preciso.

La conversión de captura se aplica a cada expresión individualmente; esto conduce a algunos resultados tontos:

<T> void test1(List<T> a){}
<T> void test2(List<T> a, List<T> b){}

List<?> x = ...;
test1(x);    // ok
test2(x, x); // error

(2) http://java.sun.com/docs/books/jls/tercera_edición/html/typesValues.html#4.10.2

En la comprobación de subtipos A :< B donde A implica argumentos comodín. Por ejemplo,

List<? extends Number>  :< B
<=>
Union{ List<S> | S <: Number}  :< B
<=>
List<S> :< B, for all S <: Number

De hecho, estamos comprobando la versión capturada del tipo A

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad