Java >> Programma Java >  >> JDK

10 Funzionalità di JDK 7 da rivedere, prima di dare il benvenuto a Java 8

È passato quasi un mese dal rilascio di Java 8 e sono sicuro che tutti voi state esplorando le nuove funzionalità di JDK 8. Ma, prima di approfondire completamente Java 8, è tempo di rivisitare alcune delle fantastiche funzionalità introdotte su Java 7. Se lo fai ricorda, Java 6 non era nulla sulle funzionalità, si trattava solo di modifiche e prestazioni della JVM, ma JDK 7 ha introdotto alcune fantastiche funzionalità che hanno migliorato le attività quotidiane degli sviluppatori. Perché sto scrivendo questo post ora? Perché sto parlando di Java 1.7, quando tutti parlano di Java 8? Bene, penso che non tutti gli sviluppatori Java abbiano familiarità con le modifiche introdotte in JDK 7 e a che ora può essere meglio rivisitare la versione precedente rispetto a prima di accogliere una nuova versione. Non vedo la gestione automatica delle risorse utilizzata dagli sviluppatori nella vita quotidiana, anche dopo che IDE ha ricevuto assistenza per i contenuti per questo. Anche se vedo programmatori che usano String nell'operatore Switch e Diamond per l'inferenza del tipo, ancora una volta si sa molto poco sul framework di join fork, catturando più eccezioni in un blocco catch o usando il carattere di sottolineatura sui valori letterali numerici. Quindi ho colto l'occasione per scrivere una sorta di post riassuntivo per rivedere queste modifiche convenienti e adottarle nella vita di programmazione quotidiana. Ci sono un paio di buone modifiche su NIO e la nuova File API e molte altre a livello di API, che vale anche la pena guardare. Sono sicuro che combinate con l'espressione lambda di Java 8, queste funzionalità si tradurranno in un codice molto migliore e più pulito.

  1. Digita l'inferenza
  2. Prima di JDK 1.7 introdurre un nuovo operatore <<, noto come operatore diamante per rendere disponibile l'inferenza del tipo anche per i costruttori. Prima di Java 7, l'inferenza del tipo era disponibile solo per i metodi e Joshua Bloch ha giustamente previsto in Effective Java 2nd Edition, ora è disponibile anche per il costruttore. Prima di JDK 7, si digita more per specificare i tipi sia sul lato sinistro che su quello destro dell'espressione di creazione dell'oggetto, ma ora era necessario solo sul lato sinistro, come mostrato nell'esempio seguente.

    Precedente JDK 7

    Map<String, List<String>> employeeRecords =  new HashMap<String, List<String>>();
    List<Integer> primes = new ArrayList<Integer>();

    In JDK 7

    Map<String, List<String>> employeeRecords =  new HashMap<>();
    List<Integer> primes = new ArrayList<>();

    Quindi devi digitare meno in Java 7, mentre lavori con Raccolte, dove utilizziamo pesantemente Generics. Vedi qui per informazioni più dettagliate sull'operatore diamante in Java.

  3. Stringa in Switch
  4. Prima di JDK 7, solo i tipi integrali possono essere utilizzati come selettore per l'istruzione switch-case. In JDK 7, puoi utilizzare un oggetto String come selettore. Ad esempio,

    String state = "NEW";
    
    switch (day) {
       case "NEW": System.out.println("Order is in NEW state"); break;
       case "CANCELED": System.out.println("Order is Cancelled"); break;
       case "REPLACE": System.out.println("Order is replaced successfully"); break;
       case "FILLED": System.out.println("Order is filled"); break;
       default: System.out.println("Invalid");
    
    }

    Il metodo equals() e hashcode() di java.lang.String viene utilizzato in confronto, con distinzione tra maiuscole e minuscole. Il vantaggio dell'utilizzo di String in switch è che il compilatore Java può generare codice più efficiente rispetto all'utilizzo dell'istruzione if-then-else nidificata. Vedere qui per informazioni più dettagliate su come utilizzare l'istruzione case String su Switch.

  5. Gestione automatica delle risorse
  6. Prima di JDK 7, è necessario utilizzare un blocco finally, per garantire che una risorsa venga chiusa indipendentemente dal fatto che l'istruzione try venga completata normalmente o bruscamente, ad esempio durante la lettura di file e flussi, è necessario chiuderli in un blocco definitivo, che risulta in un sacco di targa caldaia e codice disordinato, come mostrato di seguito:

    public static void main(String args[]) {
            FileInputStream fin = null;
            BufferedReader br = null;
            try {
                fin = new FileInputStream("info.xml");
                br = new BufferedReader(new InputStreamReader(fin));
                if (br.ready()) {
                    String line1 = br.readLine();
                    System.out.println(line1);
                }
            } catch (FileNotFoundException ex) {
                System.out.println("Info.xml is not found");
            } catch (IOException ex) {
                System.out.println("Can't read the file");
            } finally {
                try {
                    if (fin != null) fin.close();
                    if (br != null) br.close();
                } catch (IOException ie) {
                    System.out.println("Failed to close files");
                }
            }
        }

    Guarda questo codice, quante righe di codici caldaia?

    Ora in Java 7, puoi utilizzare la funzione Prova con risorse per chiudere automaticamente le risorse, che implementa l'interfaccia AutoClosable e Closeable, ad es. Stream, file, handle di socket, connessioni al database ecc. JDK 7 introduce un'istruzione try-with-resources, che assicura che ciascuna delle risorse in try(resources) sia chiusa alla fine dell'istruzione chiamando il metodo close() di AutoClosable . Ora lo stesso esempio in Java 7 apparirà come sotto, un codice molto conciso e più pulito:

    public static void main(String args[]) {
           try (FileInputStream fin = new FileInputStream("info.xml");
      BufferedReader br = new BufferedReader(new InputStreamReader(fin));) {
      if (br.ready()) {
       String line1 = br.readLine();
       System.out.println(line1);
      }
     } catch (FileNotFoundException ex) {
      System.out.println("Info.xml is not found");
     } catch (IOException ex) {
      System.out.println("Can't read the file");
     }
    }

    Poiché Java si occupa della chiusura delle risorse aperte, inclusi file e flussi, potrebbe non esserci più alcuna perdita di descrittori di file e probabilmente un errore di fine del descrittore di file. Anche JDBC 4.1 è stato adattato anche come AutoClosable.

  7. Fork Join Framework
  8. Il framework fork/join è un'implementazione dell'interfaccia ExecutorService che consente di sfruttare più processori disponibili nei server moderni. È progettato per lavori che possono essere suddivisi in parti più piccole in modo ricorsivo. L'obiettivo è utilizzare tutta la potenza di elaborazione disponibile per migliorare le prestazioni dell'applicazione. Come con qualsiasi implementazione di ExecutorService, il framework fork/join distribuisce le attività ai thread di lavoro in un pool di thread. Il framework di join fork è distinto perché utilizza un algoritmo di furto del lavoro, che è molto diverso dall'algoritmo del produttore del consumatore. I thread di lavoro che esauriscono le cose da fare possono rubare attività da altri thread che sono ancora occupati. Il centro del framework fork/join è la classe ForkJoinPool, un'estensione della classe AbstractExecutorService. ForkJoinPool implementa l'algoritmo di furto del lavoro di base e può eseguire processi ForkJoinTask. È possibile eseguire il wrapping del codice in una sottoclasse ForkJoinTask come RecursiveTask (che può restituire un risultato) o RecursiveAction. Vedi qui per ulteriori informazioni sul framework fork join in Java.

  9. Carattere di sottolineatura in valori letterali numerici
  10. In JDK 7, puoi inserire caratteri di sottolineatura '_' tra le cifre in valori letterali numerici (letterali integrali e in virgola mobile) per migliorare la leggibilità. Ciò è particolarmente utile per le persone che utilizzano grandi numeri nei file di origine, può essere utile nei domini finanziari e informatici. Ad esempio,

    int billion = 1_000_000_000;  // 10^9
    long creditCardNumber =  1234_4567_8901_2345L; //16 digit number
    long ssn = 777_99_8888L;
    double pi = 3.1415_9265;
    float  pif = 3.14_15_92_65f;

    Puoi mettere il trattino basso in punti convenienti per renderlo più leggibile, ad esempio per grandi quantità ha senso inserire il trattino basso tra tre cifre e per i numeri di carta di credito, che sono lunghi 16 cifre, ha senso mettere il trattino basso dopo la 4a cifra, poiché sono stampati nelle carte. A proposito, ricorda che non puoi mettere il trattino basso, subito dopo il numero decimale o all'inizio o alla fine del numero. Ad esempio, i seguenti valori letterali numerici non sono validi, a causa del posizionamento errato del carattere di sottolineatura:

    double pi = 3._1415_9265; // underscore just after decimal point
    long creditcardNum = 1234_4567_8901_2345_L; //underscore at the end of number
    long ssn = _777_99_8888L; //undersocre at the beginning

    Vedi il mio post su come usare il trattino basso sui valori letterali numerici per ulteriori informazioni e casi d'uso.

  11. Cattura di più tipi di eccezioni in un blocco di cattura singolo
  12. In JDK 7, un singolo blocco catch può gestire più di un tipo di eccezione.

    Ad esempio, prima di JDK 7, sono necessari due blocchi catch per rilevare due tipi di eccezioni, sebbene entrambi svolgano attività identiche:

    try {
    
       ......
    
    } catch(ClassNotFoundException ex) {
       ex.printStackTrace();
    } catch(SQLException ex) {
       ex.printStackTrace();
    }

    In JDK 7, puoi utilizzare un singolo blocco catch, con tipi di eccezione separati da '|'.

    try {
    
       ......
    
    } catch(ClassNotFoundException|SQLException ex) {
    
       ex.printStackTrace();
    
    }

    A proposito, ricorda solo che le alternative in un'istruzione multi-catch non possono essere correlate tramite sottoclassi. Ad esempio, un'istruzione multi-catch come quella di seguito genererà un errore in fase di compilazione:

    try {
    
       ......
    
    } catch (FileNotFoundException | IOException ex) {
    
       ex.printStackTrace();
    
    }

    Le alternative in un'istruzione multi-catch non possono essere correlate dalla sottoclasse, genererà un errore in fase di compilazione:java.io.FileNotFoundException è una sottoclasse di java.io.IOException alternativa su Test.main(Test.java:18)

    vedere qui per ulteriori informazioni sulla migliore gestione delle eccezioni in Java SE 7.

  13. Litterali binari con prefisso "0b"
  14. In JDK 7, puoi esprimere valori letterali in binario con il prefisso '0b' (o '0B') per i tipi integrali ( byte, short, int e long), simili al linguaggio C/C++. Prima di JDK 7, puoi utilizzare solo valori ottali (con prefisso '0') o valori esadecimali (con prefisso '0x' o '0X').

    int mask = 0b01010000101;

    o ancora meglio

    int binary = 0B0101_0000_1010_0010_1101_0000_1010_0010;

  15. Java NIO 2.0
  16. Java SE 7 ha introdotto il pacchetto java.nio.file e il relativo pacchetto, java.nio.file.attribute, fornisce un supporto completo per l'I/O dei file e per l'accesso al file system predefinito. Ha anche introdotto la classe Path che consente di rappresentare qualsiasi percorso nel sistema operativo. La nuova API del file system integra quella precedente e fornisce diversi metodi utili per controllare, eliminare, copiare e spostare i file. ad esempio, ora puoi verificare se un file è nascosto in Java. Puoi anche creare collegamenti simbolici e fisici dal codice Java. La nuova API di file JDK 7 è anche in grado di cercare file utilizzando caratteri jolly. Ottieni anche supporto per guardare una directory per le modifiche. Consiglierei di controllare il documento Java del nuovo pacchetto di file per saperne di più su questa interessante funzione utile.

  17. G1 Garbage Collector
  18. JDK 7 ha introdotto un nuovo Garbage Collector noto come G1 Garbage Collection, che è prima una forma abbreviata di spazzatura. G1 Garbage Collector esegue la pulizia dove c'è più spazzatura. Per raggiungere questo obiettivo, ha diviso la memoria heap Java in più regioni invece di 3 regioni nella versione precedente di Java 7 (spazio nuovo, vecchio e permgen). Si dice che G1 sia abbastanza prevedibile e fornisca una maggiore produttività per applicazioni ad alta intensità di memoria.

  19. Rilancio più preciso dell'eccezione
  20. Il compilatore Java SE 7 esegue un'analisi più precisa delle eccezioni generate nuovamente rispetto alle versioni precedenti di Java SE. Ciò consente di specificare tipi di eccezione più specifici nella clausola throws di una dichiarazione di metodo. prima di JDK 7, la generazione di un'eccezione veniva considerata come la generazione del tipo del parametro catch. Ad esempio, se il tuo blocco try può generare ParseException e IOException. Per catturare tutte le eccezioni e rilanciarle, dovresti catturare Exception e dichiarare il tuo metodo come un'eccezione. Questa è una sorta di lancio oscuro e non preciso, perché stai lanciando un tipo di eccezione generale (invece di quelli specifici) e le istruzioni che chiamano il tuo metodo devono catturare questa eccezione generale. Ciò sarà più chiaro vedendo il seguente esempio di gestione delle eccezioni nel codice precedente a Java 1.7

    public void obscure() throws Exception{
        try {
            new FileInputStream("abc.txt").read();
            new SimpleDateFormat("ddMMyyyy").parse("12-03-2014");        
        } catch (Exception ex) {
            System.out.println("Caught exception: " + ex.getMessage());
            throw ex;
        }
    }

    Da JDK 7 in poi puoi essere più preciso mentre dichiari il tipo di eccezione nella clausola throws di qualsiasi metodo. Questa precisione nel determinare quale Eccezione viene generata dal fatto che, se si lancia nuovamente un'eccezione da un blocco catch, si sta effettivamente generando un tipo di eccezione che:

      1. il tuo blocco try può essere lanciato,
      2. non è stato gestito da nessun precedente catch block e
      3. è un sottotipo di una delle eccezioni dichiarate come parametro catch

    Ciò porta a un migliore controllo delle eccezioni generate nuovamente. Puoi essere più preciso sulle eccezioni generate dal metodo e gestirle molto meglio sul lato client, come mostrato nel seguente esempio:

    public void precise() throws ParseException, IOException {
        try {
            new FileInputStream("abc.txt").read();
            new SimpleDateFormat("ddMMyyyy").parse("12-03-2014");        
        } catch (Exception ex) {
            System.out.println("Caught exception: " + ex.getMessage());
            throw ex;
        }
    }

    Il compilatore Java SE 7 consente di specificare i tipi di eccezione ParseException e IOException nella clausola throws nella dichiarazione del metodo preciese() perché è possibile generare nuovamente un'eccezione che è un supertipo di uno qualsiasi dei tipi dichiarati nei throws, stiamo lanciando java.lang.Exception, che è la super classe di tutte le eccezioni verificate. Inoltre in alcuni punti vedrai la parola chiave finale con il parametro catch, ma non è più obbligatorio.

Questo è tutto su ciò che puoi rivedere in JDK 7. Tutte queste nuove funzionalità di Java 7 sono molto utili nel tuo obiettivo verso il codice pulito e la produttività degli sviluppatori. Con l'espressione lambda introdotta in Java 8, questo obiettivo di un codice più pulito in Java ha raggiunto un'altra pietra miliare. Fammi sapere, se pensi che abbia omesso qualche caratteristica utile di Java 1.7, che pensi dovrebbe essere qui.

PS Se ami i libri, potrebbe piacerti anche Java 7 Nuove funzionalità Cookbook di Packet Publication.

Etichetta Java