Generica e cancellazione del tipo

9

I generici in Java sono implementati usando la cancellazione dei tipi. JLS afferma che l'ispirazione era la compatibilità con le versioni precedenti. Dove, d'altra parte, i generici C # sono reifiable.

In teoria quali sono i vantaggi e gli svantaggi di avere i farmaci generici come "cancellazione" o "reifiable"?

Java è mancante su qualcosa?

    
posta Jatin 21.11.2012 - 11:34
fonte

3 risposte

8

Bene, la motivazione (retrocompatibilità) è sia un vantaggio che uno svantaggio. È uno svantaggio perché preferiremmo tutti avere tipi reifiable, ma il prezzo da pagare era alto. Considera le scelte di progettazione in C #. Hanno tipi reificabili, ma ora hanno API duplicate. Quindi, immagina un'API Java in cui disponiamo anche di API duplicate per ogni classe parametrizzata. Ora immagina di trasferire migliaia di righe di codice dalle classi legacy alle nuove classi generiche. Ora, chi non considererebbe le API duplicate uno svantaggio? Ma hey, hanno tipi reificabili!

Quindi, la motivazione principale era "evoluzione, non rivoluzione". E logicamente, ogni decisione ha dei compromessi.

Oltre agli altri svantaggi menzionati, potremmo anche aggiungere il fatto che la cancellazione dei tipi può essere difficile da ragionare in fase di compilazione, dal momento che non è evidente che alcuni tipi verranno rimossi, e ciò porta a risultati molto bizzarri e difficili da trovare errori.

L'esistenza di metodi bridge (questo metodo generato dal sintetizzatore per mantenere la compatibilità binaria) può anche essere visto come uno svantaggio. E questi possono essere proprio uno dei motivi degli errori che ho menzionato nel paragrafo precedente.

I principali svantaggi derivano dal fatto già ovvio che esiste una singola classe e non più classi per tipi generici. Come altro esempio, consideriamo che l'overload di un metodo con la stessa classe generica non funziona in Java:

public void doSomething(List<One>);
public void doSomething(List<Two>);

Qualcosa che potrebbe essere visto come uno svantaggio di tipi reifiable (almeno in C #) è il fatto che causano esplosione del codice . Ad esempio List<int> è una classe, e List<double> è un'altra completamente diversa, in quanto è un List<string> e un List<MyType> . Quindi le classi devono essere definite in fase di esecuzione, causando un'esplosione di classi e il consumo di risorse preziose mentre vengono generate.

Riguardo al fatto che non è possibile definire un new T() in Java, menzionato in un'altra risposta, è anche interessante considerare che questo non è solo una questione di cancellazione del tipo. Richiede anche l'esistenza di un costruttore predefinito, ecco perché C # richiede un "nuovo vincolo" per questo. (Vedi Perché la nuova T () non è possibile in Java , di Alex Buckley).

    
risposta data 21.11.2012 - 14:04
fonte
6

Lo svantaggio della cancellazione di tipi è che non si conosce in fase di runtime il tipo di generico. Ciò implica che non è possibile applicare la riflessione su di essi e non è possibile istanziarli in fase di runtime.

Non puoi fare qualcosa di simile in Java:

public class MyClass<T> {
    private T t;

    //more methods    
    public void myMethod() {
        //more code
        if (someCondition) {
            t = new T();//illegal
        } else {
            T[] array = new T[];//illegal
        }            
    }       
}

C'è una soluzione alternativa per questo, ma richiede più codice. Il vantaggio, come hai detto, è la retrocompatibilità.

    
risposta data 21.11.2012 - 12:26
fonte
3

Un altro vantaggio dei generici cancellati è che i diversi linguaggi che compilano la JVM utilizzano strategie diverse per i generici, ad es. Il sito di definizione di Scala rispetto alla covarianza del sito di utilizzo di Java. Anche i generici di Scala più generosi sarebbero stati più difficili da supportare sui tipi reificati di .Net, perché essenzialmente Scala su .Net ignorava il formato di reificazione incompatibile di C #. Se avessimo avuto generici reificati nella JVM, molto probabilmente quei generici reificati non sarebbero adatti per le caratteristiche che ci piacciono davvero di Scala, e saremmo bloccati con qualcosa di subottimale. Citando da blog di Ola Bini ,

What this all means is that if you want to add reified generics to the JVM, you should be very certain that that implementation can encompass both all static languages that want to do innovation in their own version of generics, and all dynamic languages that want to create a good implementation and a nice interfacing facility with Java libraries. Because if you add reified generics that doesn’t fulfill these criteria, you will stifle innovation and make it that much harder to use the JVM as a multi language VM.

Personalmente non considero la necessità di usare un contesto TypeTag legato in Scala per i metodi in sovraccarico in conflitto come uno svantaggio, perché sposta l'overhead e l'inflessibilità della reificazione da un globale (intero programma e tutte le possibili lingue) a un problema con il sito di utilizzo per lingua, meno frequente.

    
risposta data 20.09.2013 - 03:07
fonte

Leggi altre domande sui tag