Pregunta

Tengo la siguiente clase en un jar común:

public class Common 
{
  public Common(List list)
  {
    ...  
  }  
}

Luego, cambio el parámetro del constructor de una List a una Collection de la siguiente manera:

public class Common 
{
  public Common(Collection collection)
  {
    ...
  }
}

La reconstrucción del jar común y la ejecución del sistema causan un NoSuchMethodError en cualquier clase dependiente cuando invoca al constructor hasta que yo recompile esa clase.

Tengo algunas ideas sobre lo que está causando esto, en el sentido de cómo el constructor está vinculado en el código de bytes de la clase dependiente, pero no estoy 100% seguro.

Por favor, ¿alguien puede arrojar algo de luz sobre lo que está pasando aquí?

Actualizar

Posteriormente hice una prueba rápida y le eché un vistazo al código de bytes:

Compiled from "Client.java"
public class Client extends java.lang.Object{
public Client();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   new #2; //class ArrayList
   3:   dup
   4:   invokespecial   #3; //Method java/util/ArrayList."<init>":()V
   7:   astore_1
   8:   new #4; //class Common
   11:  dup
   12:  aload_1
   13:  invokespecial   #5; //Method Common."<init>":(Ljava/util/List;)V
   16:  pop
   17:  return

}

Como dijo Tom, y como puede ver en la línea 13, el constructor exacto está vinculado en el momento de la compilación.

Aprendes algo nuevo todos los días :-)

¿Fue útil?

Solución

javac resuelve exactamente qué método o constructor llamar en tiempo de compilación. Esto no ocurre en el momento del enlace. Como la firma del constructor ha cambiado, el paso de vinculación no puede encontrar el método solicitado y, por lo tanto, arroja un error. Puede corregir el error proporcionando a los constructores, uno que toma una Collection y la otra List . Más tarde, se podría agregar un constructor que toma un Iterable .

Tenga en cuenta que los tipos genéricos no forman parte de la firma, por lo que se pueden cambiar sin perder la compatibilidad binaria. Tanto los parámetros como los tipos de devolución forman parte de la firma de los métodos (las devoluciones covariantes hacen que se creen métodos de puente sintéticos).

Hay una buena sección grande en el JLS definiendo exactamente lo que constituye cambios compatibles binarios.

Otros consejos

¿Importa las clases correctas de Lista y Colección? es decir, java.util.List y java.util.Collection ?

Creo que podría ser un problema con la versión de la biblioteca. ¿Estás seguro de que no hay otra versión de la biblioteca commons en otro lugar en el mismo contexto?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top