Conosciamo tutti Java per le sue caratteristiche grazie alle quali, nonostante siano passati più di 20 anni dalla prima versione,è tutt'oggi uno dei linguaggi più studiati e più utilizzati, malgrado la crescente diffusione di Python.
Una delle forti pecche rimane comunque il fatto che sia molto prolisso e per anni Oracle non ha dato alcun segni di cambiamento. Finalmente, con la versione 12 qualcosa sembra cambiare. Java sembra muoversi verso un modo di programmare che, in un futuro che sembra ancora lontano, permetta di scrivere codice più compatto senza perdere leggibilità e soprattutto mantenendo la portabilità che ha sempre lo ha sempre contraddistinto.
Vediamo alcune novità importanti.
Miglioramento delle switch expressions
La cosa fondamentale da dire è che questa funzione è stata introdotta come funzione sperimentale nella JEP 325, il che significa che se pur l'implementazione è completa e funzionante, potrebbe non essere riconfermata nelle versioni successive.
Una cosa decisamente interessante è il fatto che il costrutto preveda l'utilizzo della freccia ->.
Quali sono le novità fondamentali?
- Non è necessario usareil break per ogni case;
- Si possono definire diverse costanti per lo stesso case;
- Il caso default è obbligatorio;
- Il break può essere usato per restituire i valori dello switch;
Vediamo un esempio:
String stagione= ""; switch (mese) { case "marzo": case "aprile": case "maggio": { stagione= "primavera"; break; } case "giugno": case "luglio": case "agosto": { stagione= "estate"; break; } };
Mentre ora, con questo nuova sintassi, il medesimo programma diventerebbe:
String stagione=switch(mese){ case "marzo", "aprile", "maggio":{ break "primavera"; } case "giugno", "luglio", "agosto":{ break "estate"; }default ->{ break "altra stagione"; } };
Questa nuova forma di switch, spesso risulta molto comoda, magari in ambito GUI dove potrebbe capitare che diversi tasti facciano la stessa cosa, o abbiano funzioni in comune.
Nuovo modo per confrontare i file: File.mismatch()
La firma del metodo è:
public static long mismatch(Path path, Path path2) throws IOException
L'idea alla base è quella di restituire la distanza tra i due file, restituendo -1L se i file sono uguali. Due file possono essere diversi quando:
- Ci sono dei byte diversi, allora viene restituita la posizione del primo byte diverso;
- La dimensione non è la stessa, quindi viene restituita la minore;
Utile sì, assolutamente sì!
Notazione compatta dei numeri
Veongono introdotti nuovi metodi per la notazione compatta dei numeri a seconda del locale scelto.
public class CompactNumberFormatDemo { private static void esempiCompactNumberFormatting(final long numberToFormat){ final NumberFormat nfDefault = NumberFormat.getCompactNumberInstance(); final NumberFormat nfItShort = NumberFormat.getCompactNumberInstance(Locale.ITALY, NumberFormat.Style.SHORT); final NumberFormat nfItLong = NumberFormat.getCompactNumberInstance(Locale.ITALY, NumberFormat.Style.LONG); final NumberFormat nfFrShort = NumberFormat.getCompactNumberInstance(Locale.FRANCE, NumberFormat.Style.SHORT); final NumberFormat nfFrLong = NumberFormat.getCompactNumberInstance(Locale.FRANCE, NumberFormat.Style.LONG); out.println("Numero da formattare '" + numberToFormat + "':"); out.println("tDefault: " + nfDefault.format(numberToFormat)); out.println("tIT/Short: " + nfItShort.format(numberToFormat)); out.println("tIT/Long: " + nfItLong.format(numberToFormat)); out.println("tFR/Short: " + nfFrShort.format(numberToFormat)); out.println("tFR/Long: " + nfFrLong.format(numberToFormat)); } public static void main(final String[] arguments) { esempiCompactNumberFormatting(15000); } }
Otterremo come risultato:
Numero da formattare '15000':
Default: 15K
IT/Short: 15.000
IT/Long: 15 mila
FR/Short: 15 k
FR/Long: 15 mille
Teeing collector
Il principio di funzionamento è simile a quello del comando tee, familiare agli utenti unix, che redireziona l’input ai due collectors prima di fare il merge dei loro risultati mediante una Bi-function.
var result = Stream.of("Andreas", "Antonia", "Lucia", "Francesco").collect(Collectors.teeing( // primo collector Collectors.filtering(n -> n.contains("c"), Collectors.toList()), // secondo collector Collectors.filtering(n -> n.endsWith("s"), Collectors.toList()), // merger Bi-function (List list1, List list2) -> List.of(list1, list2) )); System.out.println(result); // -> [[Lucia, Francesco], [Andreas]]
JEP 305: Pattern Matching for instanceof (Preview)
Finalmente non è più necessario effettuare il casting esplicito prima di usare un oggetto.
// Prima di java 12 if (obj instanceof String) { String s = (String) obj; // usa s come stringa } // In java 12 e forse anche dopo... if (obj instanceof String s) { // è possibile usare s come stringa direttamente senza bisogno del casting }
Altre novità
- Sono stati introdotti ulteriori metodi per la classe String. Ulteriori informazioni sono reperibili sulla documentazione ufficiale :
- indent(int n);
- transform(Function f);
- Optional describeConstable();
- String resolveConstantDesc(MethodHandles.Lookup lookup);
- Con la JEP334 è stata introdotta una nuova classe java.lang.constant che contiene i descrittori nominali di vari tipi di costanti.
In definitiva, come accennato prima, Java sembra finalmente muoversi verso una sintassi che rende il codice più semplice, anche se le funzioni che appaiono più interessanti rimangono una preview. Personalmente, sono proprio curioso di seguire gli sviluppi di questa versione.
Non avrei mantenuto l'utilizzo delle variabili var, in uso da Java 10, che possono essere non tipizzate un po' sulla falsariga di JavaScript. Nonostante ciò riconosco che talvolta può essere utile anche se le variabili var possono essere utilizzate solo con scope locale. Ad oggi Java continua a non interpretare var come una keyword, quindi una parola dedicata al linguaggio, ma ne riconosce comunque il significato. Chissà, magari con il passare del tempo e delle generazioni di programmatori, l'uso diventerà più frequente e diventerà una keyword.
Parlando di tempistiche, quali sono le date relative alle varie release?
- 13/12/2019 Prima fase di distribuzione
- 17/01/2019 Seconda fase di distribuzione
- 07/02/2019 Rilascio di una versione beta
- 19/03/2019 Disponibilità generale
Vale la pena passare a Java12?
Secondo me, assolutamente sì! In particolare per i programmatori smanettoni che hanno voglia di provare la nuova versione appena arriva. Personalmente, rifarei altre mille volte il passaggio! Ho trovato addirittura qualche miglioramento, penso dovuto al cambio di algoritmo del garbage collector, che si chiama Shenandoah e che non tiene più conto della dimensione dello heap.
Al contrario, per i neofiti potrebbe essere conveniente iniziare con la versione precedente, che è sicuramente più stabile e non ha grandi differenze. Nel momento in cui la versione diventerà stabile con le varie features definitive, sarà sicuramente interessante fare l'upgrade.