Vincoli durante la progettazione dei generici Java

6

I generici Java sembrano molto diversi da quelli disponibili in Scala, sebbene entrambi siano stati progettati da Martin Odersky. Dal mio punto di vista, la progettazione di generici in Java è peggiore, ad esempio:

  • non è possibile specificare la varianza
  • si può aggirare la limitazione precedente usando i caratteri jolly, ma questo significa che l'onere di specificare la varianza va al chiamante invece che al progettista della libreria
  • non è possibile utilizzare un costruttore di tipi in generici

Quali sono stati i vincoli in Java che hanno costretto Odersky a progettare questo meccanismo per i generici anziché quello più flessibile che ha ideato per Scala? Era solo più savio pochi anni dopo o c'erano reali limitazioni a causa di Java?

    
posta Andrea 05.10.2012 - 17:25
fonte

1 risposta

8

Come notato da @FrustratedWithFormsDesigner, la compatibilità all'indietro era l'unico grosso ostacolo. E la risoluzione che scelsero fu di mantenere la compatibilità con le versioni precedenti usando tipo di cancellazione , cioè rimuovendo tutte le informazioni di tipo generico durante la compilazione. Ciò significa che List<String> e List<Integer> diventeranno lo stesso tipo in fase di esecuzione (e lo stesso di un pre-Java5 List ). E ha molte conseguenze negative, inclusa la maggior parte di ciò che hai elencato sopra.

Aggiornamento

I vincoli impostati da questo sono molto più stringenti di quanto si possa pensare ingenuamente:

What we require is that the same client code works with both the legacy and generic versions of a library. This means that the supplier and clients of a library can make completely independent choices about when to move from legacy to generic code. This is a much stronger requirement than backward compatibility; it is called migration compatibility or platform compatibility.

Java implements generics via erasure, which ensures that legacy and generic versions usually generate identical class files, save for some auxiliary information about types. It is possible to replace a legacy class file by a generic class file without changing, or even recompiling, any client code; this is called binary compatibility.

( Generics e raccolte Java , capitolo 5)

La compatibilità binaria non è sempre automaticamente garantita; la sezione 8.4 dello stesso libro descrive alcuni casi in cui la compatibilità binaria può rompersi durante la generalizzazione delle interfacce legacy anche se sono state seguite tutte le regole generali.

Un altro aspetto della retrocompatibilità è l'aderenza a un sistema di tipi in cui non tutto è un oggetto. Quindi in Java i tipi primitivi sono fuori portata per i generici proprio come per le collezioni, e si ha boxing / unboxing per complicare la vita (mentre in Scala tutto è un oggetto).

Una terza eredità in Java è costituita da array nativi che non si adattano semplicemente ai generici:

    Gli array
  • sono sempre tipi modificabili, mentre i tipi generici no;
  • Gli array
  • possono memorizzare tipi primitivi mentre le raccolte (generiche) non possono;
  • il sottotipo dell'array è covariante, mentre il sottotipo generico è invariante;
  • di conseguenza, gli array sono meno sicuri del tipo dei generici e si può sostenere che dovrebbero essere dichiarati obsoleti a favore delle raccolte generiche e non utilizzati nel nuovo codice.

Tutto ciò significa molte più regole da rispettare, quindi casi angusti e compromessi da fare, limitando la potenza e la semplicità dei generici Java.

Diverse decisioni di questo tipo possono essere viste a posteriori come errate, ma non c'è più modo di tornare indietro, quindi nessuna possibilità di risolverle senza compromettere la compatibilità con le versioni precedenti, che - giustamente o meno - è diventata una sorta di santa mucca in Java anni. Immagino che la storia dei generici di Java abbia probabilmente portato molta esperienza e spunti di riflessione per i suoi stessi designer, e queste esperienze sono state sicuramente riutilizzate durante la progettazione di Scala.

    
risposta data 05.10.2012 - 17:38
fonte

Leggi altre domande sui tag