Domanda

Ho la seguente classe in un vaso comune:

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

Quindi cambio il parametro del costruttore da un Elenco a un Collection come segue:

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

La ricostruzione del vaso comune e l'esecuzione del sistema provoca un NoSuchMethodError in qualsiasi classe dipendente quando invoca il costruttore fino a quando non ricompilerò quella classe.

Ho alcune idee su cosa sta causando questo, sulla falsariga di come il costruttore è vincolato nel bytecode della classe dipendente, ma non ne sono sicuro al 100%.

Per favore qualcuno può far luce su ciò che sta succedendo qui?

Aggiornamento

Successivamente ho fatto un rapido test e ho dato un'occhiata al bytecode:

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

}

Come ha detto Tom, e come puoi vedere nella riga 13, l'esatto costruttore è associato al momento della compilazione.

Ogni giorno impari qualcosa di nuovo :-)

È stato utile?

Soluzione

javac risolve esattamente quale metodo o costruttore chiamare al momento della compilazione. Ciò non si verifica al momento del collegamento. Poiché la firma del costruttore è cambiata, la fase di collegamento non riesce a trovare il metodo richiesto e pertanto genera un errore. È possibile correggere l'errore fornendo ai costruttori - uno che accetta un Collection l'altro List . Successivamente è possibile aggiungere un costruttore che prende un Iterable .

Nota, i tipi generici non fanno parte della firma, quindi possono essere modificati pur mantenendo la compatibilità binaria. Sia i parametri che i tipi restituiti fanno parte della firma dei metodi (i rendimenti covarianti causano la creazione di metodi bridge sintetici).

Esiste una bella sezione nella JLS definire esattamente ciò che costituisce modifiche binarie compatibili.

Altri suggerimenti

Stai importando le classi Elenco e Raccolta corrette? cioè java.util.List e java.util.Collection ?

Penso che potrebbe essere un problema con la versione della libreria. Sei sicuro che non ci sia un'altra versione della libreria commons da qualche altra parte nello stesso contesto?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top