Dopo aver visto le caratteristiche di Java SE 7 nelle precedenti puntate, con questo sesto articolo (e con i due successivi) ci dedicheremo a Java SE8, almeno per quel che se ne sa finora. La release 8 era inizialmente attesa per l’estate 2013 ma è già posticipata all’autunno. In particolare, dopo una brevissima panoramica, ci concentriamo sulla seconda parte di Coin (‘moneta’) e sul progetto Jigsaw (‘puzzle’) che molto probabilmente finirà per slittare addirittura a Java SE 9. Gli articoli della serie, opportunamente riveduti, corretti e aggiornati, andranno a costituire un libro di riferimento che distribuiremo in formato elettronico su MokaByte.
Introduzione
Con questo articolo avviamo la nostra esplorazione di Java SE 8. Ma prima di iniziare, vale la pena ricordare che al momento in cui scriviamo (novembre 2012), Java SE 8 non è ancora stabile, quindi alcune parti potrebbero subire dei cambiamenti che, tuttavia, non dovrebbero riguardare i concetti centrali.
Java SE 8 è stata inizialmente programmata per l’estate 2013 ma è ormai sicuro che tale scadenza subirà ulteriori ritardi (per ora si parla di settembre/ottobre dello stesso anno). Inoltre, la storia di Java SE 7 ci insegna che probabilmente diverse caratteristiche programmate per Java SE 8 finiranno per essere spostate alla versione successiva (Java SE9).
Secondo i piani originari, le principali innovazioni da introdurre con Java SE 8 dovevano essere:
- molteplici proposte del progetto Coin (= “moneta”) escluse da Java SE 7;
- realizzazione del progetto di modularizzazione di Java, Jigsaw (= “puzzle”), iniziato originariamente da Sun Microsystem nel 2008.
- introduzione delle Lambda Expressions, ossia della programmazione funzionale;
Progetto Jigsaw: ancora un rinvio?
Per quanto concerne il progetto Jigsaw, le cose non stanno procedendo come ci si attendeva e quindi si va quasi sicuramente verso un notevole ritardo o addirittura un’ulteriore rinvio a versione successiva, con qualche imbarazzo in casa Oracle.
Espressioni Lambda: il futuro è la programmazione funzionale?
Il progetto Lambda, di cui abbiamo già parlato nel corso degli articoli dedicati a Java SE 7, ha creato e sta creando grande interesse intorno alla versione Java SE 8. Nel web è possibile trovare molti commenti tra persone soddisfatte dei cambiamenti e persone che invece avrebbero voluto un supporto decisamente più spinto, più orientato a Scala, per capirsi, della programmazione funzionale che da molti è considerata il vero futuro di Java. Sicuramente si tratta di un cambiamento importante di Java, sia in termini di linguaggio, sia di librerie, sia di ambiente. Ma ne discuteremo nel corso dei prossimi articoli. In questo articolo dedichiamo la nostra attenzione ai progetti Coin e JigSaw.
Coin 2
Come illustrato in uno dei precedenti articoli dedicati a Java SE 7 [1], l’obiettivo del progetto Coin è di realizzare un insieme di cambiamenti del linguaggio e della librerie, al fine di semplificare le azioni che i programmatori svolgono quotidianamente, con il vincolo di poter apportare esclusivamente variazioni minori, ossia variazioni che non includono ne’ il bytecode ne’ la JVM. Ciò significa che si tratta di cambiamenti che deve risolvere il compilatore. Sempre dallo stesso articolo, si ricorda che la comunità Java, al fine di evitare ulteriori ritardi nel rilascio di Java SE 7, ha deciso per l’attuazione del famoso “Piano B”, il quale, oltre a posticipare la consegna delle Lambda Expression e del progetto Jigsaw, ha imposto una riduzione delle nuove caratteristiche incluse del progetto Coin da far confluire nella release Java SE 7. Pertanto, diverse delle rimanenti feature verranno fatte confluire nella release Java SE 8 e probabilmente anche in Java SE 9. Allo stato attuale, non è ancora chiaro quante e quali delle proposte accettate verranno incluse in Java SE8 (sono più di sessanta!). Tuttavia vale la pena evidenziarne alcune riportate di seguito.
Stringhe multilinea / String literals
Questa feature consiste nell’aggiungere la possibilità di avere stringhe multi-linea in Java al fine di rendere il codice più elegante e leggibile. In sostanza lo sviluppatore dovrebbe poter inserire una stringa su più righe e il compilatore si dovrebbe occupare di trasformarle automanticamente in una lunga stringa con i caratteri di “andata a capo”. Non si tratta di una proposta rivoluzionaria, ma comunque potrebbe aiutare a semplificare la vita di coloro che gestiscono lunghi comandi SQL.
Operatore Elvis e Null-Safe
L’idea alla base di questa proposta è di semplificare il controllo e la gestione dei puntatori null. In particolare, l’idea consiste nell’introdurre un nuovo operatore, Elvis appunto (“!“, ossia un punto esclamativo), con il compito di permettere o terminare la navigazione degli oggetti qualora un riferimento sia nullo. Il seguente listato chiarisce la situazione.
public String getPostcode(Person person) {
String ans = null;
if (person != null) {
Name nm = person.getName();
if (nm != null) {
ans= nm.getPostcode();
}
}
return ans;
}
//Equivarrebbe a:
public String getFirstName(Person person) {
return person?.getName()?.getGivenName();
}
Metodi statici nelle interfacce
Il nome di questa feature dovrebbe essere chiaro: il linguaggio Java attualmente non consente di definire metodi statici all’interno delle interfacce, quindi l’obiettivo di questa proposta è di rimuovere tale limitazione. In particolare, si richiede la possibilità di definire l’implementazione di metodi statici all’interno delle interfacce rimuovendo la classica implicazione dei metodi definiti nelle interfacce: loro definizione nelle classi che implementano l’interfaccia. Ciò, oltre ad essere utile alla programmazione funzionale (come vedremo nei seguenti articoli) dovrebbe agevolare l’implementazione di metodi di utilità all’interno di una serie di interfacce. Alcuni esempi sono la possibilità di definire l’implementazione del metodo sort direttamente nell’interfaccia java.util.List e unmodifiableMap nell’interfaccia java.util.Map. La soluzione utilizzata attualmente consiste nel ricorrere a opportune classi separate che contengono questi metodi di utilità come java.util.Collections. Ciò ovviamente non è perfettamente OO e riduce la potenza delle API. Chiaramente, l’introduzione di questa feature richiede di rivedere le regole dell’ereditarietà singola e forse multipla, nonche’ altri aspetti non secondari.
Array di grandi dimensioni
Gli array in Java sono accessibili tramite interi a 32-bit. Ciò significa che la dimensione massima teorica è di 2^31 = 2.147.483.647 elementi. Si tratta di un limite sicuramente accettabile che tuttavia può creare problemi ad applicazioni che invece devono fare i conti con grandi insiemi di dati sequenziali da mantenere in memoria. In queste situazioni risulterebbe decisamente vantaggioso poter disporre di array indicizzati con indici a 64 bit. Una soluzione immediata potrebbe essere di estendere questa feature a tutti i casi. Tuttavia come mostrato nella serie di articoli apparsi su MokaByte (cfr. [2]) ciò potrebbe portare a una riduzione delle performance. Pertanto la proposta prevede di evidenziare la richiesta di array di grandi dimensioni in modo assolutamente naturale e standard: aggiungendo la dimensione esplicita nell’array e quindi demandando al compilatore di desumere se la dimensione passa o meno il limite dei 32 bit di indirizzamento.
Sintassi per l’inizializzazione semplificata delle collection
Le classi del framework delle collezioni sono indubbiamente tra le più frequentemente utilizzate nella scrittura di programmi in Java. Come è lecito attendersi, presentano importanti analogie con array e matrici. Tuttavia, a differenza degli array, le collezioni non permettono un’inizializzazione semplificata: è necessario ricorrere a particolari blocchi statici e/o a classi annidate anonime. Pertanto, questa proposta mira a fornire tali strumenti, ossia un supporto del linguaggio Java aggiuntivo che consenta una concisa inizializzazione delle collezioni a tempo di compilazione (Concise Collection Initialization Syntax).
Operatori di uguaglianza / operatori di equivalenza
Nell’implementazione delle classi Java è molto frequente eseguire l’override del metodo equals (Object.equals) e di implementare l’interfaccia Comparable
a $$ b "same as":
(a==null ? b==null : a.equals(b), or a == b for primitive types.
a !$ b "not same as":
a==null ? b!=null : !a.equals(b), or a != b for primitive types.
a >$ b "greater than or same":
a.compareTo(b) >= 0, or a >= b for primitive types.
a <$ b "less than or same":
a.compareTo(b) <= 0, or a <= b for primitive types.
Oltre a permettere l'overloading degli operatori come segue:
a < b a.compareTo(b) < 0, or a < b for primitive types.
a > b a.compareTo(b) > 0, or a > b for primitive types.
questa proposta presenta diversi punti di contatto con le espressioni Lambda e soprattutto una soluzione divergente. Pertanto è interessante vedere se si punterà esclusivamente sulle espressioni Lambda o se si tenterà comunque di portare avanti entrambi gli approcci.
Annotazioni per i tipi
Il supporto delle annotazioni è stata una delle novità introdotte in Java 1.5 (aka J2SE 5.0) di maggiore successo che tra l'altro ha posto le basi per una mini rivoluzione nel mondo degli application server. Tuttavia, il loro utilizzo fin qui (Java SE 7) è limitato ai parametri dei metodi, alla dichiarazione di package, classi, metodi, field e variabili locali. La proposta type annotations lancia l'idea di un utilizzo più generale e quindi più utile delle annotazioni. In particolare, l'idea consiste nel poter annotare la dichiarazione di tipo al fine di migliorare la qualità del codice e per prevenire/individuare a tempo di compilazione errori che altresì emergerebbero a tempo di esecuzione. La proposta tuttavia si limita a specificare la sintassi e non la semantica evitando così la necessità di dover modificare il compilatore, e l'ambiente di esecuzione. Ciò equivale a dire che le annotazioni dei tipi risulterebbero dei controlli "pluggable" ad uso e consumo di opportuni pre-processori.
Jigsaw
Lo scopo del progetto Jigsaw è disegnare e realizzare un sistema modulare standard per la piattaforma Java SE da applicare sia alla stessa piattaforma, sia al JDK. Si tratta di realizzare un sistema che sia una sorta di mix tra Maven (cfr. [3]) e OSGi (l'acronimo deriva originariamente da Open Services Gateway initiative). Da una parte Maven da solo non è sufficiente. Maven è un tool per la gestione e comprensione dei progetti e quindi è uno strumento alquanto valido per organizzare progetti, gestirne il ciclo di vita, le relative informazioni, e così via, ma per sua natura, si limita agli aspetti relativi a tempo di costruzione (build-time). In altre parole, Maven non si occupa di aspetti di modularizzazione relativi al tempo di esecuzione. Dall'altro lato, anche OSGi, che logicamente può essere collocato all'altro estremo del campo di competenza, considerato da solo non è sufficiente. Il framework OSGi è un sistema modulare e una piattaforma di servizi per il linguaggio di programmazione Java che implementa un modello a componenti completo e dinamico. OSGi, pertanto, si occupa degli aspetti di modularizzazione a tempo di esecuzione (per essere precisi interviene a partire dal packaging includendo il deployment e l'esecuzione) e molto meno degli aspetti di organizzazione del progetto. Pertanto, almeno da un punto di vista teorico, Jigsaw dovrebbe essere un'opportuna combinazione tra Maven e OSGi, combinazione, che ad onore del vero è già una sorta di realtà in diverse organizzazioni. Il limite di questa strategia è che si tratta di una soluzione creata a partire dalla piattaforma Java, mentre una vera innovazione dovrebbe richiedere cambiamenti più radicali a partire dalla stessa piattaforma. Si tratta di un compito complicato considerando che la base di partenza è un code-base che si è evoluto negli anni secondo un modello non modulare o almeno non nel modo appropriato per dar luogo ad una vera modularizzazione dell'ambiente. Una conseguenza di ciò, per esempio, è che il codice JDK sia profondamente interconnesso sia alle API sia ai vari livelli di implementazione. Pertanto, una completa e accurata implementazione del progetto richiede un lavoro propedeutico atto a eliminare o quanto meno minimizzare le varie dipendenze. Ciò è necessario per far sì che sia la piattaforma e le sue implementazioni possano effettivamente diventare un insieme coerente di moduli interdipendenti.
Stato del progetto
La realizzazione del progetto Jigsaw era prevista per SE 7 e poi per Java SE 8. Al fine di raggiungere quest'ultimo obiettivo, il lavoro sulle caratteristiche principali dovrebbe essere terminato entro maggio 2013, ciò per consentire la preparazione di una versione finale per settembre. Nonostante importanti progressi, ci sono ancora una serie di problemi tecnici non banali. La mancanza di tempo finisce per complicarne ulteriormente l'evoluzione. Quindi, la proposta di Reinhold (Chief Architect del Java Platform Group presso Oracle) nel suo blog [4] consiste nel rinviare ulteriormente il progetto Jigsaw alla release ancora successiva, cioè Java SE 9. Inoltre, al fine di aumentare la prevedibilità di tutte le future release Java SE, Reinhold propone di stabilire il ciclo di rilascio delle nuove versioni su un arco di tempo di due anni.
Sempre secondo Reinhold, nonostante i progressi, permangono ancora importanti problemi tecnici, tra cui la completa modularizzazione della piattaforma Java SE e del JDK, mantenendo, al tempo stesso, la compatibilità con il codice esistente. Si tratta ovviamente di un compito estremamente delicato che richiede modifiche ben ponderate in ogni parte, a partire dalle specifiche per finire all'implementazione e test. Inoltre, è necessario progettare e realizzare un prototipo di strumenti di sostegno come IDE, application server, Java EE container e applet container, i quali tendono a sfruttare massicciamente binding dinamici e reflection. Lo stato del progetto lascia pensare che il team sia ragionevolmente sicuro di essere in grado di risolvere questi problemi, tuttavia è innegabile che si sia accumulato un certo ritardo tanto da compromettere l'attuale deadline dell'intera release di Java SE 8.
Chiaramente, l'introduzione di una piattaforma veramente modulare è un passaggio importante che, alla fine, influenza l'intero ecosistema Java. Questa ha la potenzialità di cambiare il modo in cui la piattaforma Java stessa viene distribuita, il modo in cui gli sviluppatori creeranno e distribuiranno librerie, framework, tool e applicazioni. Pertanto è di fondamentale importanza avere tempo sufficiente per la revisione generale, per eseguire test ed analizzare il feedback ricevuto da tutti i segmenti della comunità Java relativi sia alla progettazione, sia sull'implementazione.
Possibili scenari
A questo punto, quindi, le opzioni disponibili sono "tristemente" prevedibili sulla base dell'esperienza di Java SE 7:
- posporre a Java SE 9 la consegna del progetto Jigsaw al fine di non ritardare la consegna di Java SE 8 con le altre caratteristiche;
- attendere la conclusione dei lavori del progetto Jigsaw, per includerlo insieme alle altre nuove caratteristiche, nella prossima, completa, release di Java SE: questa alernativa farebbe slittare la consegna di della versione Java SE 8 verso la metà del 2014.
Questo nuovo piano B è oggetto di accese discussioni all'interno della comunità Java e, come da protocollo, la decisione finale è affidato al JSR 337 Expert Group.
Conclusioni
Con questo articolo abbiamo avviato l'esplorazione di Java SE 8. Sebbene al momento non sia ancora stabile, e quindi alcune parti potrebbero subire dei cambiamenti (e ci potete contare che succederà!), è lecito attendersi che le parti core non cambino significativamente. Per quanto attiene il progetto Jigsaw, sono state prese in considerazione ben sessanta proposte (oltre quelle già consegnate con Java SE 7) e di queste, ovviamente, sarà possibile consegnarne solo un limitato sottoinsieme. Le più interessanti sono: Elvis and Other Null-Safe Operators che permette di migliorare notevolmente la qualità del codice semplificando i ricorrenti controlli dei riferimenti nulli; static methods in interface, che consiste nel rendere possibile incapsulare metodi statici nelle interfacce al fine di realizzare codice più OO riducendo la necessità di ricorrere a classi ausiliari; large array ossia il supporto per gli array di grandi dimensioni; sintassi più concisa per l'inizializzazione delle collezioni e un supporto più conciso per eseguire il test di uguaglianza e il supporto per diversi tipi di annotazione.
Lo scopo del progetto Jigsaw è disegnare e realizzare un sistema modulare standard per la piattaforma Java SE da applicare sia alla stessa piattaforma, sia al JDK. Si tratta di realizzare un sistema che sia una sorta di mix tra Maven e OSGi. Jigsaw è in forte ritardo rispetto alla pianificazione iniziale, il che è anche comprensibile visto e considerato l'enorme impatto sull'intero ecosistema Java. A questo punto è lecito chiedersi se Jigsaw arriverà in tempo o se si preferirà rimandarne l'incorporazione a una successiva versione di Java SE.
Riferimenti
[1] Luca Vetti Tagliati, "L'evoluzione di Java: verso Java 8 - III parte: Java SE 7 e la ‘moneta' delle nuove feature", MokaByte 173, maggio 2012
https://www.mokabyte.it/cms/article.run?articleId=ORJ-HZ8-Q45-F8N_7f000001_3893887_2d8c237e
[2] Luca Vetti Tagliati, "Java e le architetture a 64 bit: i puntatori compressi", MokaByte 157, dicembre 2010
https://www.mokabyte.it/cms/article.run?articleId=D7E-Q8S-USB-URM_7f000001_24511967_e20206eb
[3] Luca Vetti Tagliati, "Maven: best practices per il processo di build e di rilascio dei progetti in Java - I parte: Panoramica e filosofia d'uso", MokaByte 114, gennaio 2007
https://www.mokabyte.it/cms/article.run?articleId=S85-L5J-HP3-86O_7f000001_30480431_0844866c
[4] Mark Reinhold, "There's not a moment to lose! Project Jigsaw: Late for the train", 17 luglio 2012
http://mreinhold.org/blog/late-for-the-train