Java 9 - Guida rapida

JAVA 9 (aka jdk 1.9) è una versione importante dello sviluppo del linguaggio di programmazione JAVA. La sua versione iniziale è stata rilasciata il 21 settembre 2017. Gli obiettivi principali del rilascio di Java 9 sono:

  • Rendere la piattaforma JDK e Java Standard Edition modulare, nel senso che può essere ridotta a piccoli dispositivi di elaborazione.

  • Per migliorare la sicurezza complessiva delle implementazioni JDK e Java.

  • Per rendere il processo di compilazione e la manutenzione di librerie di codici java e applicazioni di grandi dimensioni facili per piattaforme JAVA SE ed EE.

  • Progettare e implementare un sistema di moduli standard per la piattaforma Java che può essere applicato facilmente sia sulla piattaforma che su JDK.

Nuove caratteristiche

Ci sono oltre 90 miglioramenti aggiunti a Java 8, i più significativi sono menzionati di seguito:

  • Module - Un nuovo tipo di componente di programmazione Java introdotto come modulo, che è una raccolta denominata e auto-descrittiva di codice e dati.

  • REPL (JShell) - Funzionalità REPL (Read-Eval-Print Loop) aggiunta alla piattaforma Java.

  • HTTP 2 Client - nuova API HTTPClient che supporta websocket e flussi HTTP 2 e funzionalità server push.

  • Improved JavaDocs- Supporta la generazione di output HTML5. Fornisce una casella di ricerca per la documentazione API generata.

  • Multirelease JAR - Migliora il formato JAR in modo che più versioni specifiche di Java dei file di classe possano coesistere in un unico archivio.

  • Collection Factory Methods - Nuovi metodi factory statici per le interfacce List, Set e Map per creare istanze immutabili di tali raccolte.

  • Private Interface Methods - Interfacce migliorate con metodi statici privati ​​e privati.

  • Process API Improvements - API migliorata per controllare e gestire i processi del sistema operativo.

  • Stream API Improvements - Maggiore sicurezza e robustezza consentendo di filtrare i flussi in entrata dei dati di serializzazione degli oggetti.

  • Try With Resources improvement - Ora le variabili finali possono essere utilizzate come risorse nell'istruzione try-with-resources.

  • Enhanced @Deprecated Annotation - @ Annotazione obsoleta rinnovata per fornire ulteriori informazioni sullo stato e sulla disposizione prevista di un'API.

  • Inner Class Diamond Operator - Consenti l'utilizzo dell'operatore diamante con classi anonime se è possibile indicare il tipo di argomento del tipo dedotto.

  • Optional Class Improvements - Nuovi metodi utili vengono aggiunti alla classe java.util.Optional.

  • Multiresolution Image API - Supporta l'incapsulamento di una serie di immagini con diverse risoluzioni in un'unica immagine multirisoluzione.

  • CompletableFuture API improvements - I meccanismi asincroni della classe CompletableFuture possono eseguire un'azione quando il processo esce con il metodo ProcessHandle.onExit.

  • Lightweight JSON - Un'API leggera introdotta per consumare e generare documenti e flussi di dati tramite json in java 9.

  • Reactive Streams API - È stata introdotta una nuova API Reactive Streams in Java SE 9 per supportare la programmazione reattiva in java 9.

Configurazione dell'ambiente locale

Se desideri configurare il tuo ambiente per il linguaggio di programmazione Java, questa sezione ti guida attraverso l'intero processo. Seguire i passaggi indicati di seguito per configurare il proprio ambiente Java.

Java SE è disponibile per il download gratuito. Per scaricare clicca qui , scarica una versione compatibile con il tuo sistema operativo.

Segui le istruzioni per scaricare Java ed esegui il file .exeper installare Java sulla tua macchina. Dopo aver installato Java sulla macchina, sarà necessario impostare le variabili di ambiente in modo che puntino alle directory di installazione corrette.

Impostazione del percorso per Windows 2000 / XP

Supponendo che tu abbia installato Java nella directory c: \ Program Files \ java \ jdk -

  • Fare clic con il pulsante destro del mouse su "Risorse del computer" e selezionare "Proprietà".

  • Fare clic sul pulsante "Variabili d'ambiente" nella scheda "Avanzate".

  • Ora, modifica la variabile "Path" e aggiungi il percorso alla directory eseguibile Java alla fine di essa. Ad esempio, se il percorso è attualmente impostato su C:\Windows\System32, modificalo nel modo seguente

C:\Windows\System32;c:\Program Files\java\jdk\bin

Impostazione del percorso per Windows 95/98 / ME

Supponendo che tu abbia installato Java nella directory c: \ Program Files \ java \ jdk -

  • Modifica il file "C: \ autoexec.bat" e aggiungi la seguente riga alla fine:

SET PATH = %PATH%;C:\Program Files\java\jdk\bin

Configurazione del percorso per Linux, UNIX, Solaris, FreeBSD

La variabile d'ambiente PATH dovrebbe essere impostata in modo che punti a dove sono stati installati i binari Java. Fare riferimento alla documentazione della shell se si hanno problemi a farlo.

Ad esempio, se usi bash come shell, aggiungi la seguente riga alla fine del tuo .bashrc -

export PATH = /path/to/java:$PATH'

Editor Java popolari

Per scrivere programmi Java, è necessario un editor di testo. Sul mercato sono disponibili IDE ancora più sofisticati. I più popolari sono descritti brevemente di seguito:

  • Notepad- Su una macchina Windows, puoi usare qualsiasi semplice editor di testo come Blocco note (consigliato per questo tutorial) o WordPad. Notepad ++ è anche un editor di testo gratuito che migliora le funzionalità.

  • Netbeans - È un IDE Java open-source e gratuito da cui è possibile scaricare https://www.netbeans.org/index.html.

  • Eclipse - È anche un IDE Java sviluppato dalla comunità open source di Eclipse e può essere scaricato da https://www.eclipse.org/.

IDE o Integrated Development Environment, fornisce tutti gli strumenti e le strutture comuni per aiutare nella programmazione, come editor di codice sorgente, strumenti di compilazione e debugger ecc.

Java 9, è stato introdotto un nuovo tipo di componente di programmazione chiamato module. Un modulo è una raccolta di codice e dati che si autodefinisce e ha un nome per identificarlo.

Caratteristiche

Con il componente Modules, sono stati aggiunti i seguenti miglioramenti in Java 9:

  • Viene introdotta una nuova fase facoltativa, il tempo di collegamento. Questa fase è intermedia tra il tempo di compilazione e il tempo di esecuzione. Durante questa fase, un set di moduli può essere assemblato e ottimizzato, creando un'immagine runtime personalizzata utilizzando lo strumento jlink.

  • javac, jlink e java hanno opzioni aggiuntive per specificare i percorsi dei moduli, che individuano ulteriormente le definizioni dei moduli.

  • Formato JAR aggiornato come JAR modulare, che contiene il file module-info.class nella sua directory principale.

  • Introduzione del formato JMOD, un formato di packaging (simile a JAR) che può includere codice nativo e file di configurazione.

Creazione del modulo

Seguendo i passaggi per creare un modulo, dì com.tutorialspoint.greetings.

Passo 1

Crea una cartella C: \> JAVA \ src. Ora crea una cartella com.tutorialspoint.greetings che è uguale al nome del modulo che stiamo creando.

Passo 2

Crea module-info.java in C: \> JAVA \ src \ com.tutorialspoint.greetings cartella con il seguente codice.

module-info.java

module com.tutorialspoint.greetings { }

module-info.java è il file che viene utilizzato per creare il modulo. In questo passaggio abbiamo creato un modulo denominato com.tutorialspoint.greetings. Per convenzione questo file dovrebbe risiedere nella cartella il cui nome è uguale al nome del modulo.

Passaggio 3

Aggiungi il codice sorgente nel modulo. Crea Java9Tester.java nella cartella C: \> JAVA \ src \ com.tutorialspoint.greetings \ com \ tutorialspoint \ greetings con il seguente codice.

Java9Tester.java

package com.tutorialspoint.greetings;

public class Java9Tester {
   public static void main(String[] args) {
      System.out.println("Hello World!");
   }
}

Per convenzione, il codice sorgente di un modulo deve trovarsi nella stessa directory che è il nome del modulo.

Passaggio 4

Crea una cartella C: \> JAVA \ mods. Ora crea una cartella com.tutorialspoint.greetings che è uguale al nome del modulo che abbiamo creato. Ora compila il modulo nella directory mods.

C:/ > JAVA > javac -d mods/com.tutorialspoint.greetings 
   src/com.tutorialspoint.greetings/module-info.java 
   src/com.tutorialspoint.greetings/com/tutorialspoint/greetings/Java9Tester.java

Passaggio 5

Eseguiamo il modulo per vedere il risultato. Esegui il seguente comando.

C:/ > JAVA > java --module-path mods -m com.tutorialspoint.greetings/com.tutorialspoint.greetings.Java9Tester

Qui module-path fornisce la posizione del modulo come mod e -m indica il modulo principale.

Produzione

Stamperà il seguente output sulla console.

Hello World!

REPL sta per Read-Eval-Print Loop. Con JShell, java ha la capacità REPL. Utilizzando REPL, possiamo codificare e testare la logica basata su java senza compilare usando javac e vedere direttamente il risultato dei calcoli.

Esecuzione di JShell

Apri il prompt dei comandi e digita jshell.

$ jshell
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro
jshell>

Visualizzazione dei comandi JShell

Digita / help una volta avviato il comando jshell.

jshell> /help
|  Type a Java language expression, statement, or declaration.
|  Or type one of the following commands:
|  /list [<name or id>|-all|-start]
|  list the source you have typed
|  /edit <name or id>
|  edit a source entry referenced by name or id
|  /drop <name or id>
|  delete a source entry referenced by name or id
|  /save [-all|-history|-start] <file>
|  Save snippet source to a file.
|  /open <file>
|  open a file as source input
|  /vars [<name or id>|-all|-start]
|  list the declared variables and their values
|  /methods [<name or id>|-all|-start]
|  list the declared methods and their signatures
|  /types [<name or id>|-all|-start]
|  list the declared types
|  /imports 
|  list the imported items

Esecuzione del comando JShell

Digita / imports una volta avviato il comando jshell e visualizza le importazioni utilizzate.

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
jshell>

Esecuzione di calcoli in JShell.

Prova a eseguire semplici calcoli in JShell.

jshell> 3+1
$1 ==> 4 jshell> 13%7 $2 ==> 6
jshell> $2 $2 ==> 6
jshell>

Creazione e utilizzo di funzioni in JShell

Crea una funzione doubled () per prendere int e restituire il suo valore raddoppiato.

jshell> int doubled(int i){ return i*2;}
|  created method doubled(int)
jshell> doubled(6)
$3 ==> 12
jshell>

Uscita da JShell

Digita / esci.

jshell> /exit
| Goodbye

La documentazione Java può essere generata utilizzando lo strumento javadoc. Attualmente genera documentazione in formato html 4.0. In java 9, possiamo generare documentazione in formato html 5 utilizzando l'opzione -html5 negli argomenti della riga di comando.

Documentazione java vecchio stile

Considera il seguente codice nella cartella C: / JAVA.

Tester.java

/**
 * @author MahKumar
 * @version 0.1
 */
public class Tester {
   /**
   * Default method to be run to print 
   * <p>Hello world</p>
   * @param args command line arguments
   */
   public static void main(String []args) {
      System.out.println("Hello World");
   }
}

Ora esegui lo strumento javadoc di jdk 7 per generare la documentazione.

C:\JAVA>javadoc -d C:/JAVA Tester.java
Loading source file tester.java...
Constructing Javadoc information...
Standard Doclet version 1.7.0_21
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

Creerà la pagina della documentazione java nella directory C: / JAVA e vedrai il seguente output.

Nuova documentazione java con supporto per la ricerca e HTML5

Esegui lo strumento javadoc di jdk 9 con il flag -html5 per generare un nuovo tipo di documentazione.

C:\JAVA> javadoc -d C:/JAVA -html5 Tester.java
Loading source file Tester.java...
Constructing Javadoc information...
Standard Doclet version 9.0.1
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

Creerà la pagina di documentazione java aggiornata nella directory D: / test e vedrai il seguente output.

In java 9, viene introdotta una nuova funzionalità in cui un formato jar è stato migliorato per avere versioni diverse della classe java o le risorse possono essere mantenute e utilizzate secondo la piattaforma. In JAR, un file MANIFEST.MF ha una voce Multi-Release: true nella sua sezione principale. La directory META-INF contiene anche una sottodirectory delle versioni le cui sottodirectory (che iniziano con 9 per Java 9) memorizzano classi specifiche della versione e file di risorse.

In questo esempio, utilizzeremo un jar multi-release per avere due versioni del file Tester.java, una per jdk 7 e una per jdk 9 e lo eseguiremo su diverse versioni di jdk.

Passi

Step 1- Crea una cartella c: / test / java7 / com / tutorialspoint. Crea Test.java con il seguente contenuto:

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 7");
   }
}

Step 2- Crea una cartella c: / test / java9 / com / tutorialspoint. Crea Test.java con il seguente contenuto:

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 9");
   }
}

Compila i codici sorgente.

C:\test > javac --release 9 java9/com/tutorialspoint/Tester.java

C:\JAVA > javac --release 7 java7/com/tutorialspoint/Tester.java

Crea il vaso multi-rilascio

C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9.
Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java, 
   multiple resources with same name

Corri con JDK 7

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 7

Corri con JDK 9

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 9

Con Java 9, vengono aggiunti nuovi metodi di fabbrica alle interfacce List, Set e Map per creare istanze immutabili. Questi metodi factory sono metodi factory convenienza per creare una raccolta in modo meno dettagliato e conciso.

Vecchio modo per creare collezioni

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = new HashSet<>();
      set.add("A");
      set.add("B");
      set.add("C");
      set = Collections.unmodifiableSet(set);
      System.out.println(set);
      List<String> list = new ArrayList<>();

      list.add("A");
      list.add("B");
      list.add("C");
      list = Collections.unmodifiableList(list);
      System.out.println(list);
      Map<String, String> map = new HashMap<>();

      map.put("A","Apple");
      map.put("B","Boy");
      map.put("C","Cat");
      map = Collections.unmodifiableMap(map);
      System.out.println(map);
   }
}

Produzione

Stamperà il seguente output.

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}

Nuovi metodi

Con java 9, i seguenti metodi vengono aggiunti alle interfacce List, Set e Map insieme alle loro controparti sovraccariche.

static <E> List<E> of(E e1, E e2, E e3);
static <E> Set<E>  of(E e1, E e2, E e3);
static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)

Punti da notare

  • Per le interfacce List e Set, il metodo of (...) viene sovraccaricato per avere da 0 a 10 parametri e uno con il parametro var args.

  • Per l'interfaccia Map, il metodo of (...) viene sovraccaricato per avere da 0 a 10 parametri.

  • In caso di più di 10 parametri per l'interfaccia Map, è possibile utilizzare il metodo ofEntries (...) che accetta il parametro var args.

Nuovo modo per creare collezioni

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = Set.of("A", "B", "C");      
      System.out.println(set);
      List<String> list = List.of("A", "B", "C");
      System.out.println(list);
      Map<String, String> map = Map.of("A","Apple","B","Boy","C","Cat");
      System.out.println(map);
  
      Map<String, String> map1 = Map.ofEntries (
         new AbstractMap.SimpleEntry<>("A","Apple"),
         new AbstractMap.SimpleEntry<>("B","Boy"),
         new AbstractMap.SimpleEntry<>("C","Cat"));
      System.out.println(map1);
   }
}

Produzione

Stamperà il seguente output.

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}
{A=Apple, B=Boy, C=Cat}

Prima di Java 8, le interfacce possono avere i seguenti tipi di variabili / metodi.

  • Variabili costanti
  • Metodi astratti

Quindi non possiamo avere l'implementazione del metodo nelle interfacce o più precisamente un'implementazione predefinita prima di Java 8. Vedi l'esempio.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

final class LogMySql implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   void logInfo(String message);
   void logWarn(String message);
   void logError(String message);
   void logFatal(String message);

   void getConnection();
   void closeConnection();
}

Produzione

Vedrai il seguente output.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Nell'esempio precedente, ogni metodo di log ha la propria implementazione. Con Java 8 le interfacce possono avere i seguenti tipi di variabili / metodi.

  • Variabili costanti
  • Metodi astratti
  • Metodi predefiniti
  • Metodi statici

Facciamo implementazione predefinita e metodi statici nell'interfaccia stessa usando Java 8.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   default void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }
   
   default void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }
   
   default void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }
   
   default void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   static void getConnection() {
      System.out.println("Open Database connection");
   }
   static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

Produzione

Vedrai il seguente output.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Nell'esempio sopra, abbiamo di nuovo la ripetizione. Con Java 9 le interfacce possono avere i seguenti tipi di variabili / metodi.

  • Variabili costanti
  • Metodi astratti
  • Metodi predefiniti
  • Metodi statici
  • Metodi privati
  • Metodi statici privati

Disponiamo di metodi privati ​​e li usiamo in Java 9.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   private void log(String message, String prefix) {
      getConnection();
      System.out.println("Log Message : " + prefix);
      closeConnection();
   }
   
   default void logInfo(String message) {
      log(message, "INFO");
   }
   
   default void logWarn(String message) {
      log(message, "WARN");
   }
   
   default void logError(String message) {
      log(message, "ERROR");
   }
   
   default void logFatal(String message) {
      log(message, "FATAL");
   }

   private static void getConnection() {
      System.out.println("Open Database connection");
   }
   
   private static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

Produzione

Vedrai il seguente output.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

In Java 9 Process API, responsabile del controllo e della gestione dei processi del sistema operativo, è stata notevolmente migliorata. ProcessHandle Class ora fornisce l'ID del processo nativo del processo, l'ora di inizio, il tempo di CPU accumulato, gli argomenti, il comando, l'utente, il processo padre e i discendenti. La classe ProcessHandle fornisce anche un metodo per controllare la vivacità dei processi e per distruggere i processi. Ha il metodo onExit, la classe CompletableFuture può eseguire l'azione in modo asincrono quando il processo termina.

Tester.java

import java.time.ZoneId;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.io.IOException;

public class Tester {
   public static void main(String[] args) throws IOException {
      ProcessBuilder pb = new ProcessBuilder("notepad.exe");
      String np = "Not Present";
      Process p = pb.start();
      ProcessHandle.Info info = p.info();
      System.out.printf("Process ID : %s%n", p.pid());
      System.out.printf("Command name : %s%n", info.command().orElse(np));
      System.out.printf("Command line : %s%n", info.commandLine().orElse(np));

      System.out.printf("Start time: %s%n",
         info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
         .toLocalDateTime().toString()).orElse(np));

      System.out.printf("Arguments : %s%n",
         info.arguments().map(a -> Stream.of(a).collect(
            Collectors.joining(" "))).orElse(np));

      System.out.printf("User : %s%n", info.user().orElse(np));
   } 
}

Produzione

Vedrai il seguente output.

Process ID : 5800
Command name : C:\Windows\System32\notepad.exe
Command line : Not Present
Start time: 2017-11-04T21:35:03.626
Arguments : Not Present
User: administrator

I flussi sono stati introdotti in Java per aiutare gli sviluppatori a eseguire operazioni aggregate da una sequenza di oggetti. Con Java 9, vengono aggiunti pochi metodi in più per migliorare i flussi.

takeWhile (Predicate Interface)

Sintassi

default Stream<T> takeWhile(Predicate<? super T> predicate)

Il metodo takeWhile accetta tutti i valori finché il predicato non restituisce false. Restituisce, in caso di flusso ordinato, un flusso costituito dal prefisso più lungo di elementi presi da questo flusso che corrispondono al predicato dato.

Esempio

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
         .forEach(System.out::print);		 
   } 
}

Produzione

takeWhile metodo accetta tutti i valori a, be c, quindi una volta che la stringa è vuota, ha smesso di essere eseguito.

abc

dropWhile (Predicate Interface)

Sintassi

default Stream<T> dropWhile(Predicate<? super T> predicate)

Il metodo dropWhile elimina tutti i valori all'inizio finché il predicato non restituisce true. Restituisce, in caso di flusso ordinato, un flusso costituito dagli elementi rimanenti di questo flusso dopo aver eliminato il prefisso più lungo di elementi corrispondenti al predicato dato.

Esempio

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
      System.out.println();
      Stream.of("a","b","c","","e","","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
   } 
}

Produzione

drop Mentre il metodo elimina i valori a, bec, quindi una volta che la stringa è vuota, prende tutti i valori.

ef
ef

iterare

Sintassi

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

Il metodo iterate ora ha il predicato hasNext come parametro che arresta il ciclo una volta che il predicato hasNext restituisce false.

Esempio

import java.util.stream.IntStream;

public class Tester {
   public static void main(String[] args) {
      IntStream.iterate(3, x -> x < 10, x -> x+ 3).forEach(System.out::println);
   } 
}

Produzione

3
6
9

ofNullable

Sintassi

static <T> Stream<T> ofNullable(T t)

Il metodo ofNullable viene introdotto per prevenire NullPointerExceptions e per evitare controlli null per i flussi. Questo metodo restituisce un flusso sequenziale contenente un singolo elemento, se non nullo, altrimenti restituisce un flusso vuoto.

Esempio

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      long count = Stream.ofNullable(100).count();
      System.out.println(count);
  
      count = Stream.ofNullable(null).count();
      System.out.println(count);
   } 
}

Produzione

1
0

L'istruzione try-with-resources è un'istruzione try con una o più risorse debitamente dichiarate. Qui la risorsa è un oggetto che dovrebbe essere chiuso una volta che non è più necessario. L'istruzione try-with-resources garantisce che ogni risorsa venga chiusa al termine del requisito. Qualsiasi oggetto che implementa java.lang.AutoCloseable o java.io.Closeable, interfaccia può essere utilizzato come risorsa.

Prima di Java 9, le risorse devono essere dichiarate prima di try o all'interno dell'istruzione try come mostrato di seguito nell'esempio fornito. In questo esempio, useremo BufferedReader come risorsa per leggere una stringa e poi BufferedReader deve essere chiuso.

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (BufferedReader br1 = br) {
         return br1.readLine();
      }
   }
}

Produzione

test

Qui dobbiamo dichiarare una risorsa br1 all'interno dell'istruzione try e quindi usarla. In Java9, non è più necessario dichiarare br1 e il programma successivo darà lo stesso risultato.

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (br) {
         return br.readLine();
      }
   }
}

Produzione

test

@ L'annotazione precedente è stata introdotta nella versione java 5. Un elemento del programma annotato con @Deprecated significa che non dovrebbe essere usato per nessuno dei seguenti motivi:

  • Il suo utilizzo può portare a errori.
  • Potrebbe essere incompatibile nella versione futura.
  • Potrebbe essere rimosso nella versione futura.
  • Un'alternativa migliore ed efficiente l'ha sostituita.

Il compilatore genera avvisi ogni volta che viene utilizzato un elemento deprecato. Con Java 9, vengono apportati due nuovi miglioramenti all'annotazione @Deprecated.

  • forRemoval- Indica se l'elemento annotato è soggetto a rimozione in una versione futura. Il valore predefinito è falso.

  • since- Restituisce la versione in cui l'elemento annotato è diventato obsoleto. Il valore predefinito è la stringa vuota.

Deprecato con da allora

L'esempio seguente della classe booleana javadoc su Java 9 illustra l'uso dell'attributo since nell'annotazione @Deprecated.

Classe booleana

Deprecato con forRemoval

Il seguente esempio di javadoc della classe di sistema su Java 9 illustra l'uso dell'attributo forRemoval sull'annotazione @Deprecated.

Classe di sistema

L'operatore Diamond è stato introdotto in java 7 per rendere il codice più leggibile ma non può essere utilizzato con le classi interne anonime. In java 9, può essere utilizzato anche con una classe anonima per semplificare il codice e migliorare la leggibilità. Considera il codice seguente prima di Java 9.

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<Integer>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<Object>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

Produzione

1
2
Test

Con Java 9, possiamo usare l'operatore <> con la classe anonima come mostrato di seguito.

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

Produzione

1
2
Test

La classe facoltativa è stata introdotta in Java 8 per evitare controlli null e problemi di NullPointerException. In Java 9, vengono aggiunti tre nuovi metodi per migliorarne le funzionalità.

  • stream()
  • ifPresentOrElse()
  • or()

metodo stream ()

Sintassi

public Stream<T> stream()

Se è presente un valore, restituisce uno Stream sequenziale contenente solo quel valore, altrimenti restituisce uno Stream vuoto.

Esempio

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Tester {
public static void main(String[] args) {
   List<Optional<String>> list = Arrays.asList (
      Optional.empty(), 
      Optional.of("A"), 
      Optional.empty(), 
      Optional.of("B"));

   //filter the list based to print non-empty values
  
   //if optional is non-empty, get the value in stream, otherwise return empty
   List<String> filteredList = list.stream()
      .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
      .collect(Collectors.toList());

   //Optional::stream method will return a stream of either one 
   //or zero element if data is present or not.
   List<String> filteredListJava9 = list.stream()
      .flatMap(Optional::stream)
      .collect(Collectors.toList());

      System.out.println(filteredList);
      System.out.println(filteredListJava9);
   }  
}

Produzione

[A, B]
[A, B]

ifPresentOrElse () metodo

Sintassi

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

Se è presente un valore, esegue l'azione data con il valore, altrimenti esegue l'azione a base vuota data.

Esempio

import java.util.Optional;

public class Tester {
   public static void main(String[] args) {
      Optional<Integer> optional = Optional.of(1);

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));

      optional = Optional.empty();

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));
   }  
}

Produzione

Value: 1
Not Present.

o () metodo

Sintassi

public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

Se è presente un valore, restituisce un Opzionale che descrive il valore, altrimenti restituisce un Opzionale prodotto dalla funzione di fornitura.

Esempio

import java.util.Optional;
import java.util.function.Supplier;

public class Tester {
   public static void main(String[] args) {
      Optional<String> optional1 = Optional.of("Mahesh");

      Supplier<Optional<String>> supplierString = () -> Optional.of("Not Present");

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));
    
      optional1 = Optional.empty();    

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));  
   }  
}

Produzione

Value: Mahesh
Value: Not Present

Con Java 9, è stata introdotta una nuova API di immagini multi-risoluzione che supporta più immagini con diverse varianti di risoluzione. Questa API consente di utilizzare un insieme di immagini con una risoluzione diversa come un'unica immagine a più risoluzioni. Di seguito sono riportate le principali operazioni di immagine multi-risoluzione.

  • Image getResolutionVariant(double destImageWidth, double destImageHeight) - Ottiene un'immagine specifica che è la variante migliore per rappresentare questa immagine logica alla dimensione indicata.

  • List<Image> getResolutionVariants() - Ottiene un elenco leggibile di tutte le varianti di risoluzione.

Esempio

import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.awt.Image;
import java.awt.image.MultiResolutionImage;
import java.awt.image.BaseMultiResolutionImage;

import javax.imageio.ImageIO;

public class Tester {
   public static void main(String[] args) throws IOException, MalformedURLException {

      List<String> imgUrls = List.of("http://www.tutorialspoint.com/java9/images/logo.png",
         "http://www.tutorialspoint.com/java9/images/mini_logo.png",
         "http://www.tutorialspoint.com/java9/images/large_logo.png");

      List<Image> images = new ArrayList<Image>();

      for (String url : imgUrls) {
         images.add(ImageIO.read(new URL(url)));
      }

      // read all images into one multiresolution image
      MultiResolutionImage multiResolutionImage = 
         new BaseMultiResolutionImage(images.toArray(new Image[0]));

      // get all variants of images
      List<Image> variants = multiResolutionImage.getResolutionVariants();

      System.out.println("Total number of images: " + variants.size());

      for (Image img : variants) {
         System.out.println(img);
      }

      // get a resolution-specific image variant for each indicated size
      Image variant1 = multiResolutionImage.getResolutionVariant(156, 45);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 
         156, 45, variant1.getWidth(null), variant1.getHeight(null));

      Image variant2 = multiResolutionImage.getResolutionVariant(311, 89);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 311, 89, 
         variant2.getWidth(null), variant2.getHeight(null));

      Image variant3 = multiResolutionImage.getResolutionVariant(622, 178);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 622, 178, 
         variant3.getWidth(null), variant3.getHeight(null));

      Image variant4 = multiResolutionImage.getResolutionVariant(300, 300);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 300, 300, 
         variant4.getWidth(null), variant4.getHeight(null));
   }  
}

Produzione

Total number of images: 3
BufferedImage@7ce6a65d: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =311 
height = 89 #numDataElements 4 dataOff[0] = 3

BufferedImage@4c762604: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =156 
height = 45 #numDataElements 4 dataOff[0] = 3

BufferedImage@2641e737: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =622 
height = 178 #numDataElements 4 dataOff[0] = 3

Image for destination[156,45]: [311,89]
Image for destination[311,89]: [311,89]
Image for destination[622,178]: [622,178]
Image for destination[300,300]: [622,178]

La classe CompletableFuture è stata introdotta in Java 8 per rappresentare il futuro che può essere completato impostando il suo valore e lo stato esplicitamente. Può essere utilizzato come java.util.concurrent.CompletionStage. Supporta funzioni e azioni dipendenti che sono state attivate al completamento del futuro. In java 9 l'API CompletableFuture è stata ulteriormente migliorata. Di seguito sono riportate le modifiche pertinenti apportate all'API.

  • Supporto per ritardi e timeout.
  • Supporto migliorato per le sottoclassi.
  • Aggiunti nuovi metodi di fabbrica.

Supporto per ritardi e timeout

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

Questo metodo completa questo CompletableFuture con il valore specificato se non viene completato altrimenti prima del timeout specificato.

public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

Questo metodo completa in modo eccezionale questo CompletableFuture con un'eccezione TimeoutException se non viene completato altrimenti prima del timeout specificato.

Supporto migliorato per le sottoclassi

public Executor defaultExecutor()

Restituisce l'Executor predefinito utilizzato per i metodi asincroni che non specificano un Executor. Questo metodo può essere sovrascritto nelle sottoclassi per restituire un Executor per fornire un thread indipendente come minimo.

public <U> CompletableFuture<U> newIncompleteFuture()

Restituisce un nuovo CompletableFuture incompleto del tipo che deve essere restituito da un metodo CompletionStage. Le sottoclassi della classe CompletableFuture devono sovrascrivere questo metodo per restituire un'istanza della stessa classe di CompletableFuture. L'implementazione predefinita restituisce un'istanza della classe CompletableFuture.

Nuovi metodi di fabbrica

public static <U> CompletableFuture<U> completedFuture(U value)

Questo metodo factory restituisce un nuovo CompletableFuture che è già completato con il valore specificato.

public static <U> CompletionStage<U> completedStage(U value)

Questo metodo factory restituisce un nuovo CompletionStage che è già completato con il valore dato e supporta solo i metodi presenti nell'interfaccia CompletionStage.

public static <U> CompletionStage<U> failedStage(Throwable ex)

Questo metodo factory restituisce un nuovo CompletionStage che è già completato eccezionalmente con la data eccezione e supporta solo i metodi presenti nell'interfaccia CompletionStage.

Oltre alle funzionalità menzionate, con Java 9 vengono apportati molti più miglioramenti alla piattaforma JDK. Alcuni di loro sono elencati di seguito.

  • Miglioramenti a GC (Garbage Collector)
  • API Stack-Walking
  • Filtra i dati di serializzazione in entrata
  • Ritira l'applet API
  • Indica la concatenazione di stringhe
  • Maniglie del metodo migliorate
  • API e servizio di registrazione della piattaforma Java
  • Corde compatte
  • Parser API per Nashorn