Cambiar una clase de ruptura de tipo constructor en otro jar
-
05-07-2019 - |
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 :-)
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?