He notado que JLS habla de 5.1.10 Capture Conversion, pero no entiendo cuáles son.¿Qué es una conversión de captura en Java y alguien me puede dar ejemplos?
¿Alguien me puede explicar/dar ejemplos?
He notado que JLS habla de 5.1.10 Capture Conversion, pero no entiendo cuáles son.¿Qué es una conversión de captura en Java y alguien me puede dar ejemplos?
¿Alguien me puede explicar/dar ejemplos?
La conversión de captura se diseñó para crear comodines (en genéricos), ?
útiles.
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());
}
Debido test
no es una prima Test
y desde repeatPreviousShout()
en "retrospectiva" devuelve un ?
, el compilador sabe que hay un T
que sirve como parámetro de tipo para Test
. Este T
es desconocido T
por lo que el compilador borra el tipo desconocido (para comodín, reemplaza con Object
). Por lo tanto, repeatPreviousShout()
devuelve 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 trata de hacer el control de seguridad de tipo de shout()
pero ya que recibió un comodín, que no sabe lo que T
representa, por lo tanto, crea un marcador de posición llamada captura de.
De here (Java theory and practice: Going wild with generics, Part 1), se dice claramente:
conversión de captura es lo que permite que el compilador para fabricar un nombre de tipo de marcador de posición por el comodín capturado, de manera que la inferencia de tipos puede inferir que a ser que el tipo .
Espero que esto te ayude.
Un ejemplo adicional: http://stackoverflow.com/questions/4449611/can-anyone-give-me-an-example-where-the-eclipse-jdt-creates-an-ast-with-a-captur –
@ John, si lees el artículo (enlace proporcionado anteriormente de IBMWorks), verás que el ejemplo que diste proviene de allí. –
Un tipo parametrizado que implica 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 utilizar List<? extends Number>
, Java utiliza la versión capturada List<S>
, donde S es una variable de tipo recién creado con límite superior Number
.
(1) http://java.sun.com/docs/books/jls/third_edition/html/expressions.html
Para limitar el tipo de una expresión. Si el tipo de 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 algún tipo concreto S (S <: Number>
). Por lo tanto, el compilador usa List<S>
para realizar análisis de tipo más precisos.
La conversión de captura se aplica a cada expresión individualmente; esto lleva a algunos resultados mudos:
<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/third_edition/html/typesValues.html#4.10.2
En subtipo comprobación 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
Así pues, en efecto, estamos comprobando la versión capturada de tipo A
No hay ejemplos que no sea en la discusión inmediatamente por debajo? –
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í, ¿podría explicarme amablemente cuáles son? Gracias. –