Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, February 09, 2012

I Generics e la magia nera.

 Il problema generale

La JVM non supporta e non supporterà ancora per lungo tempo (JAVA 8 ??) i reified generics . Questo ha dato luogo, negli anni, a molte polemiche sull'usabilità effettiva dei generics.
In realtà se ci si trova ad utilizzare i Generics per fare qualcosa di più avanzato, ci si scontra prima o poi col problema di dover fare qualcosa del genere:




class MyClass<T> {
private final T o;
public MyClass() {
this.o = new T();
}
}



questo NON si può fare poiché a runtime MyClass non sa niente circa la natura del parametro generico T. Vedete, il fatto è che laddove javac è capace di effettuare un controllo sintattico e di validazione semantica del nostro codice, la jre non sa niente circa il tipo generico T che è stato inferito perché l'informazione è andata completamente persa in compilazione (type erasure).
Ma, -incredibile ma vero- c'è un ma, in determinate circostanze ciò diventa possibile mediante l'utilizzo di alcune booster feature abbastanza nascoste di Java che sono le Classi Anonime.

Tramite questa feature è possibile creare a runtime delle copie "personalizzate" delle classi che sono, per così dire, "usa e getta".

Classi Anonime (CA)

Ma che cosa sono le classi anonime? E soprattutto: che cosa NON sono?
Con le CA diviene possibile fare questa cosa:


MyClass<Double> myClass = new MyClass<Double>() {

// In questo blocco si aggiungono funzionalità

// a MyClass, specializzandola


// };


può essere cioè creato un oggetto myClass istanza di una classe anonima MyClass; il che non significa che MyClass sia una classe anonima.

Infatti MyClass non è assolutamente anonima (la dichiariamo), d'altra parte utilizziamo il "potere" di aggiungere funzionalità al codice di base, cosa che caratterizza le classi anonime.

javac e le CA

Già, ma come fa il compilatore in questi casi? Da quello che abbiamo visto è chiaro: traduce nel bytecode delle strutture dati completamente caratterizzate dal punto di vista dei parametri dei tipi generici utilizzati (che è bene) e dunque non attiva la type erasure (che è male).Messa diversamente:

la summenzionata MyClass non conosce nessuna informazione di tipo quando è chiamata così:


MyClass<Double> myClass = new MyClass<Double>();

ma conosce l'informazione che deve manipolare un tipo generico quando è chiamata così:


MyClass<Double> myClass = new MyClass<Double>() { /*something here */ };

Deve essere dunque cambiata la chiamata utilizzando la nostra classe "anonimizzata", dunque:


MyClass<Double> myClass1 = new MyClass<Double>(); //type erasure happens

MyClass<Double> myClass2 = new MyClass<Double>() { }; //type erasure DOES NOT happen! :)


Come vedete, abbiamo bisogno solo dello scheletro della nostra classe anonima, e non di tutta l'implementazione, se non abbiamo bisogno di logica aggiuntiva.

La soluzione classica


Se ricordiamo per un momento il tema generale, vediamo che quello che abbia mo visto finora, benché interessante e certamente utilizzabile, non è tutto. Per completare il discorso serve...la magia (nera?).
Qui noi non siamo solo interessati a che non intervenga la type erasure da parte del compilatore, ma anche ci interessa dare alla nostra classe MyClass la possibilità di sapere che il suo parametro generico T è effettivamente un tipo (ovvero T.class).

La soluzione classica di questo problema prevede che si faccia una chiamata di questo tipo:


MyClass<Double>myClass = new MyClass<Double>(Double.class);



Questa non è una soluzione ottimale sebbene è proprio quello che fanno gli sviluppatori, in ogni caso è perfettamente lecita. Ma..è tipo...magia! Sì però non è proprio buona. Non è ottimale per esempio il ricorso alle ripetizioni del tipo "reificato" Double: chissà che sforzo il compilatore!! Scherzi a parte, quando il nostro codice cuba 5k o 10k linee (seppure organizzate secondo tutte le best practices del mondo) diventa difficile da manutenere.
Fin qui la teoria, ma io mi sono chiesto se questa cosa funzionasse sul serio, l'ho implementata per un problema abbastanza complicato (ok,ok...me lo sono complicato da solo :) ) e grazie a questo "trucchetto" ho portato a casa la giornata.
La soluzione più smart è nell'articolo da cui ho tratto spunto per redigere questo post, e del quale ringrazio l'autore. Seppure si tratta di un articolo esplicativo di un particolare framework che serve ad un task ancora più particolare, la parte generale è ben scritta e comprensibile.
Fin quando non avremo in java un'implementazione nativa dei reified generics dovremo attrezzarci con le arti...magiche! Tant'è. Stay Tuned!









Wednesday, November 28, 2007

Quando una classe java synchronyzed non è thread-safe

Oggi mi è arrivata la consueta mail della newsletter di TheServerSide.com ed era recensito un articolo che ha subito attirato la mia attenzione. L'articolo in questione parla di una delle più controverse questioni che presenta il linguaggio Java: la concorrenza e la sicurezza dei thread.
Essendo l'argomento di rilevante attenzione, specie nel mondo Enterprise in cui sicuramente ci troviamo alle prese con questioni di performance, mi interessa in modo particolare. L'articolo si trova qui. E' una buona guida al problema della concorrenza in Java e aiuta a rendersi ben conto di quello che succede a livello di codice JVM quando si itera una semplice Collection. Questo è da tenere bene a mente quando si sviluppa, speciamente in ambiente distribuito come è per la maggior parte delle applicazioni Enterprise basate su Application Server, perché spesso si crede che l'AS tenga conto di queste vulnerabilità della JDK, mentre non è sempre così. E' per questo che bisogna considerare, laddove il progetto lo richieda, l'uso del package java.util.concurrent che si prende cura di tutti i particolari legati al problema della concorrenza dei thread.

Friday, November 16, 2007

AppFuse 2.0 released

Con colpevole ritardo, dovuto ad impegni lavorativi, logorio della vita moderna ecc. ecc., mi accorgo solo oggi che la tanto attesa versione 2.0 di Appfuse è stata rilasciata. La piattaforma di sviluppo web di Matt Raible, sviluppatore j2ee molto popolare nella comunità open source nonché apprezzato autore del libro Spring Live (The Spring Primer), ha completato il ciclo di sviluppo ed ora è stata rilasciata, dopo 13 mesi di incubazione, la nuova release.
Novità di questa versione, per chi avesse utilizzato la prima, la "mavenizzazione" del prodotto che ha permesso di sostituire la distribuzione fisica del pacchetto compresso con un'installazione rapida da repository remoto. Non solo, ha permesso un'integrazione più spinta con altri prodotti accessori che prima non era possibile o lo era solo parzialmente.
Il QuickStart Tour per l'utilizzo della piattaforma è questo .