Java 8 è stato rilasciato il 18 marzo 2014. È passato molto tempo, ma ancora molti progetti sono in esecuzione su Java 8. È perché è stato un rilascio importante con molte nuove funzionalità. Vediamo tutte le funzionalità principali ed eccitanti di Java 8 con esempi di codice.
Panoramica rapida delle funzionalità di Java 8
Alcune delle importanti funzionalità di Java 8 sono;
- metodo forEach() nell’interfaccia Iterable
- metodi predefiniti e statici nelle interfacce
- Interfacce funzionali ed espressioni Lambda
- API Stream di Java per operazioni su dati in blocco su collezioni
- API Time di Java
- Miglioramenti all’API Collection
- Miglioramenti all’API di concorrenza
- Miglioramenti all’API Java IO
Facciamo una breve panoramica di queste funzionalità di Java 8. Fornirò alcuni frammenti di codice per una migliore comprensione delle funzionalità in modo semplice.
1. Metodo forEach() nell’interfaccia Iterable
Ogni volta che abbiamo bisogno di attraversare una collezione, dobbiamo creare un iteratore il cui scopo principale è iterare su di essa, e poi abbiamo la logica di business in un ciclo per ciascuno degli elementi nella collezione. Potremmo ottenere una ConcurrentModificationException se l’iteratore non viene utilizzato correttamente.
Java 8 ha introdotto il metodo forEach nell’interfaccia java.lang.Iterable in modo che, durante la scrittura del codice, ci concentriamo sulla logica di business. Il metodo forEach prende un oggetto java.util.function.Consumer come argomento, quindi aiuta a avere la nostra logica di business in un luogo separato che possiamo riutilizzare. Vediamo l’utilizzo di forEach con un semplice esempio.
Il numero di righe potrebbe aumentare, ma il metodo forEach aiuta a avere la logica per l’iterazione e la logica di business in un luogo separato, risultando in una maggiore separazione delle preoccupazioni e codice più pulito.
Metodi predefiniti e statici nelle interfacce
Se leggi attentamente i dettagli del metodo forEach, noterai che è definito nell’interfaccia Iterable ma sappiamo che le interfacce non possono avere un corpo di metodo. A partire da Java 8, le interfacce sono potenziate per avere un metodo con implementazione. Possiamo utilizzare la parola chiave default
e static
per creare interfacce con implementazione del metodo. L’implementazione del metodo forEach nell’interfaccia Iterable è:
Sappiamo che Java non fornisce ereditarietà multipla nelle classi perché porta al problema del diamante. Quindi come verrà gestito con le interfacce ora, dal momento che le interfacce sono ora simili alle classi astratte?
La soluzione è che il compilatore solleverà un’eccezione in questo scenario e dovremo fornire la logica di implementazione nella classe che implementa le interfacce.
Si noti che entrambe le interfacce hanno un metodo comune log() con una logica di implementazione.
Come puoi vedere, Interface1
ha un’implementazione del metodo statico che viene utilizzata nell’implementazione del metodo MyClass.log()
. Java 8 utilizza pesantemente i metodi default e statici nell’API Collection e i metodi di default vengono aggiunti in modo che il nostro codice rimanga retrocompatibile.
Se una classe nell’ierarchia ha un metodo con la stessa firma, allora i metodi di default diventano irrilevanti. Object è la classe di base, quindi se abbiamo metodi di default equals(), hashCode() nell’interfaccia, diventeranno irrilevanti. Ecco perché per una migliore chiarezza, non è consentito avere metodi di default di Object nelle interfacce.
Per i dettagli completi sulle modifiche delle interfacce in Java 8, si prega di leggere Modifiche alle interfacce di Java 8.
3. Interfacce Funzionali ed Espressioni Lambda
Se noti il codice dell’interfaccia sopra, noterai l’annotazione @FunctionalInterface. Le interfacce funzionali sono un nuovo concetto introdotto in Java 8. Un’interfaccia con esattamente un metodo astratto diventa un’Interfaccia Funzionale. Non è necessario utilizzare l’annotazione @FunctionalInterface per contrassegnare un’interfaccia come Interfaccia Funzionale.
@FunctionalInterface è una struttura per evitare l’aggiunta accidentale di metodi astratti nelle interfacce funzionali. Puoi pensarlo come l’annotazione @Override ed è una pratica consigliata usarla. java.lang.Runnable con un singolo metodo astratto run() è un ottimo esempio di interfaccia funzionale.
Uno dei principali vantaggi dell’interfaccia funzionale è la possibilità di utilizzare espressioni lambda per istanziarle. Possiamo istanziare un’interfaccia con una classe anonima ma il codice sembra ingombrante.
Dato che le interfacce funzionali hanno solo un metodo, le espressioni lambda possono facilmente fornire l’implementazione del metodo. È sufficiente fornire gli argomenti del metodo e la logica di business. Ad esempio, possiamo scrivere l’implementazione sopra usando un’espressione lambda come:
Se hai una singola istruzione nell’implementazione del metodo, non è necessario nemmeno l’uso delle parentesi graffe. Ad esempio, l’interfaccia anonima Interface1 sopra può essere istanziata utilizzando una lambda come segue:
Le espressioni lambda sono un modo per creare facilmente classi anonime di interfacce funzionali. Non ci sono vantaggi in fase di esecuzione nell’uso delle espressioni lambda, quindi le utilizzerò con cautela perché non mi dispiace scrivere qualche riga di codice in più.
A new package java.util.function
has been added with bunch of functional interfaces to provide target types for lambda expressions and method references. Lambda expressions are a huge topic, I will write a separate article on that in the future.
Puoi leggere il tutorial completo su Tutorial sulle Espressioni Lambda di Java 8.
4. API Stream di Java per Operazioni su Dati in Blocco su Collezioni
A new java.util.stream
has been added in Java 8 to perform filter/map/reduce like operations with the collection. Stream API will allow sequential as well as parallel execution. This is one of the best features for me because I work a lot with Collections and usually with Big Data, we need to filter out them based on some conditions.
L’interfaccia Collection è stata estesa con i metodi predefiniti stream() e parallelStream() per ottenere lo Stream per l’esecuzione sequenziale e parallela. Vediamo il loro utilizzo con un semplice esempio.
Se esegui il codice di esempio sopra, otterrai un output simile a questo:
Nota che i valori del processo parallelo non sono in ordine, quindi il processamento parallelo sarà molto utile quando si lavora con collezioni molto grandi.
Coprire tutto riguardo all’API Stream non è possibile in questo post, puoi leggere tutto sull’API Stream su Tutorial di Esempi di Java 8 Stream API.
5. API Java Time
È sempre stato difficile lavorare con Date, Tempo e Fusi Orari in Java. Non c’era un approccio standard o un’API in Java per le date e il tempo. Uno dei bei miglioramenti in Java 8 è il pacchetto java.time
che semplificherà il processo di lavoro con il tempo in Java.
Solo guardando i pacchetti dell’API Time di Java, posso intuire che saranno molto facili da usare. Ha alcuni sotto-pacchetti come java.time.format che fornisce classi per stampare e analizzare date e tempi e java.time.zone che fornisce supporto per i fusi orari e le loro regole.
La nuova API Time preferisce gli enum rispetto alle costanti intere per i mesi e i giorni della settimana. Una delle classi utili è DateTimeFormatter per convertire gli oggetti DateTime in stringhe. Per un tutorial completo, vai su Tutorial di Esempi dell’API Java Date Time.
6. Miglioramenti dell’API delle Collezioni
Abbiamo già visto il metodo forEach() e l’API Stream per le collezioni. Alcuni nuovi metodi aggiunti nell’API Collection sono:
Iterator
metodo predefinitoforEachRemaining(Consumer action)
per eseguire l’azione data per ciascun elemento rimanente fino a quando tutti gli elementi sono stati elaborati o l’azione genera un’eccezione.Collection
metodo predefinitoremoveIf(Predicate filter)
per rimuovere tutti gli elementi di questa collezione che soddisfano il predicato dato.Collection
metodospliterator()
che restituisce un’istanza di Spliterator che può essere utilizzata per attraversare gli elementi in sequenza o in parallelo.- Map
replaceAll()
,compute()
,merge()
metodi. - Miglioramento delle prestazioni per la classe HashMap con collisioni di chiavi
7. Miglioramenti dell’API di concorrenza
Alcuni importanti miglioramenti dell’API concorrente sono:
ConcurrentHashMap
metodi compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() e search().CompletableFuture
che può essere esplicitamente completato (impostando il suo valore e stato).Executors
metodonewWorkStealingPool()
per creare un pool di thread che ruba lavoro utilizzando tutti i processori disponibili come livello di parallelismo obiettivo.
8. Miglioramenti all’IO di Java
Alcuni miglioramenti dell’IO che conosco sono:
Files.list(Path dir)
che restituisce uno Stream popolato in modo pigro, gli elementi dei quali sono le voci nella directory.Files.lines(Path path)
che legge tutte le righe da un file come uno Stream.Files.find()
che restituisce uno Stream popolato in modo pigro con Path cercando file in un albero di file radicato in un dato file di partenza.BufferedReader.lines()
che restituisce uno Stream, gli elementi dei quali sono righe lette da questo BufferedReader.
Miglioramenti vari all’API di base di Java 8
Alcuni miglioramenti vari dell’API che potrebbero essere utili sono:
- Metodo statico ThreadLocal conInitial(Supplier supplier) per creare istanze facilmente.
- L’interfaccia Comparator è stata estesa con molti metodi predefiniti e statici per l’ordinamento naturale, l’ordinamento inverso, ecc.
- Metodi min(), max() e sum() nelle classi wrapper Integer, Long e Double.
- I metodi logicalAnd(), logicalOr() e logicalXor() nella classe Boolean.
- Il metodo stream() di ZipFile per ottenere uno Stream ordinato sulle voci del file ZIP. Le voci appaiono nello Stream nell’ordine in cui compaiono nel directory centrale del file ZIP.
- Svariati metodi di utilità nella classe Math.
- Il comando
jjs
è stato aggiunto per invocare l’engine Nashorn. - Il comando
jdeps
è stato aggiunto per analizzare i file di classe - Il ponte JDBC-ODBC è stato rimosso.
- Lo spazio di memoria PermGen è stato rimosso
Questo è tutto per le caratteristiche di Java 8 con esempi di programmi. Se ho saltato delle caratteristiche importanti di Java 8, per favore fatemelo sapere attraverso i commenti.
Source:
https://www.digitalocean.com/community/tutorials/java-8-features-with-examples