useful type parameter method generic example are java generics

type - Java Generics-¿Método puente?



java generics parameter (3)

Es interesante notar que el compilador infiere el método de MyComparator :

public int compare(Integer a, Integer b) {/* code */}

está tratando de anular Comparator<T> ''s

public int compare(T a, T b);

del tipo declarado Comparator<Integer> . De lo contrario, el MyComparator la compare MyComparator como un método adicional (sobrecarga) y no omiso. Y como tal, no tendría un método puente creado para ello.

Algo llamado el concepto de "puente" relacionado con Java Generics me hizo detenerme en un punto y pensar en ello.

Por cierto, solo sé que ocurre en el nivel de bytecode y no está disponible para que lo usemos.

Pero estoy ansioso por conocer el concepto detrás del "método de puente" utilizado por el compilador de Java.

¿Qué pasa exactamente detrás de las escenas y por qué se usa?

Cualquier ayuda con un ejemplo sería muy apreciada.


Es un método que permite que una clase amplíe una clase genérica o implemente una interfaz genérica (con un parámetro de tipo concreto) para seguir utilizándose como tipo sin formato.

Imagina esto:

public class MyComparator implements Comparator<Integer> { public int compare(Integer a, Integer b) { // } }

Esto no se puede usar en su forma cruda, pasando dos Object s para comparar, porque los tipos se compilan en el método de comparación (al contrario de lo que sucedería si fuera un parámetro de tipo genérico T, donde el tipo se borrará). Entonces, en lugar de eso, detrás de escena, el compilador agrega un "método puente", que se ve más o menos así (si fuera fuente Java):

public class MyComparator implements Comparator<Integer> { public int compare(Integer a, Integer b) { // } //THIS is a "bridge method" public int compare(Object a, Object b) { return compare((Integer)a, (Integer)b); } }

El compilador protege el acceso al método de puente, imponiendo que las llamadas explícitas directamente al resultado en un error de tiempo de compilación. Ahora la clase también se puede usar en su forma original:

Object a = 5; Object b = 6; Comparator rawComp = new MyComparator(); int comp = rawComp.compare(a, b);

¿Por qué más se necesita?

Además de agregar soporte para el uso explícito de tipos crudos (que es principalmente para la compatibilidad hacia atrás) también se requieren métodos de puente para admitir el borrado de tipos. Con borrado de tipo, un método como este:

public <T> T max(List<T> list, Comparator<T> comp) { T biggestSoFar = list.get(0); for ( T t : list ) { if (comp.compare(t, biggestSoFar) > 0) { biggestSoFar = t; } } return biggestSoFar; }

en realidad está compilado en bytecode compatible con esto:

public Object max(List list, Comparator comp) { Object biggestSoFar = list.get(0); for ( Object t : list ) { if (comp.compare(t, biggestSoFar) > 0) { //IMPORTANT biggestSoFar = t; } } return biggestSoFar; }

Si el método del puente no existía y MyComparator un List<Integer> y un MyComparator a esta función, la llamada en la línea etiquetada IMPORTANT fallaría ya que MyComparator no tendría un método llamado compare que tome dos Object s ... solo uno eso toma dos Integer .

Las preguntas frecuentes a continuación son una buena lectura.

Ver también:


Si quiere entender por qué necesita un método de puente, es mejor que comprenda lo que sucede sin él. Supongamos que no hay un método de puente.

class A<T>{ private T value; public void set(T newVal){ value=newVal } } class B extends A<String>{ public void set(String newVal){ System.out.println(newVal); super.set(newVal); } }

Observe que después del borrado, el método set en A se convirtió en un public void set(Object newVal) ya que no hay límite en el parámetro Tipo T. No hay ningún método en la clase B cuya firma sea la misma que la set en A. Entonces no hay anular. Por lo tanto, cuando sucedió algo como esto:

A a=new B(); a.set("Hello World!");

El polimorfismo no funcionará aquí. Recuerde que debe anular el método de la clase principal en la clase hija para que pueda usar la clase padre var para desencadenar el polimorfismo.

Lo que hace el método bridge es anular silenciosamente el método en la clase padre con toda la información de un método con el mismo nombre pero diferente firma. Con la ayuda del método bridge, el polimorfismo funcionó. Aunque en la superficie, anulas el método de clase padre con un método de firma diferente.