[x^2 for x in lst]

Nyheter i Java 8 - del 7 - Lösa trådar och uppsummering

2014-12-18

Efter ett längre uppehåll är det nu dags för den sjunde och sista delen i miniserien om nyheterna i Java 8. Förra delen handlade om nyheter i klassen Arrays. Den här delen listar lite av de nyheter i Java 8 som inte tidigare tagits upp i serien samt summerar mina intryck av Java 8 och hur det har varit att skriva den här serien av blogginlägg.

Fler nyheter i Java 8

Vi har ju gått igenom en massa nyheter i Java 8. Streams, lambdauttryck med mera. Vad finns det då ytterligare för nyheter i Java 8? Om man läser på Oracles "officiella" sida What's New in JDK 8 så ser man att det är en hel del nyhter som vi inte tagit upp (det är dock roligt att se att det är rätt mycket som vi har tagit upp också). En del av de saker vi inte tagit upp är följande:

  • Förändringar i annoteringsramverket.
  • Förbättringar när det gäller säkerhetsrelaterade saker.
  • Förbättringar av JavaFX.
  • Nya verktyg (jjs) tillagda och förbättringar är gjorda på redan befintliga.
  • Nya Date - Time-paket
  • Ny JavaScript-motor: Nashorn
  • JDBC 4.2

Flera av sakerna ovan låter intressanta att kolla på. Speciellt Nashorn borde man ju ta sig en närmare titt på. Får bli nästa år. Så mycket att göra och så lite tid... ;)

Litet Java 8-nyheter-letar-program

För skojs skull gjorde jag ett litet Java-program som kravlar igenom API-dokumentationen för Java 8 och letar efter alla klasser som innehåller "since 1.8" (se nedan) och skriver ut namnen på dessa (egentligen den fulla path:en till javadoc-html-filen) på std out. Det hittade över 300 klasser. Det är alltså en hel del klasser som är nya eller har fått nya metoder/fält i 1.8.

Angående programmet så kompliceras det lite grand av att "Since" och "1.8" inte finns på samma rad i API-dokumentationen. Programmet måste därför undersöka två rader i taget tills det antingen får en träff eller kommer till slutet på filen. I övrigt är det ett rätt okomplicerat program som startar i en startkatalog, undersöker html-filerna i den katalogen och sedan fortsätter att undesöka filerna i dess underkataloger rekursivt. Jag har inte försökt optimera programmet på något sätt, så det finns (som vanligt ;) säkert rum för förbättringar.

Programmet använder som ni set Java 8-specifika features som strömmar och lambdauttryck, vilket gör att de delar som innehåller "affärslogiken" blir ganska korta och koncisa. För att jämföra skrev jag ett motsvarande program som inte använder Java 8-features. Det blev ca 15 rader längre. Inte så stor skillnad kanske, men om man ser på programmen så är de delar som verkligen gör något avsevärt kortare i Java 8-varianten. Detta främst på grund av den trevliga metoden Stream.filter() som vi ju pratat om tidigare.

package since18Finder;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.io.File;
import java.io.FileFilter;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

public class Since18Crawler
{
  public final static String START_DIR = "/home/lars/text/docs/java/1.8/docs/api/java/";
  public final static String SINCE_1_8_ROW_1 = "Since:";
  public final static String SINCE_1_8_ROW_2 = "1.8";

  public static void main(String[] args) throws IOException
  {
    visitDirectory(Paths.get(START_DIR));
  } 

  private static void visitDirectory(Path path)
  {
    try {      
      checkFilesInDirectory(path);
      visitSubDirectories(path);
    } catch(IOException ioe) {
      ioe.printStackTrace();
    }
  }

  private static void visitSubDirectories(Path path) throws IOException {
    Files.list(path).filter(Files::isDirectory).forEach(f -> visitDirectory(f));
  }
  
  private static void checkFilesInDirectory(Path path) throws IOException {
    Files.list(path).
     filter(p -> Since18Crawler.isFileToLookIn(p)).
     filter(p -> Since18Crawler.containsString(p, SINCE_1_8_ROW_1, SINCE_1_8_ROW_2)).
     forEach(p -> System.out.println(p.toFile().getAbsolutePath()));    
  }

  private static boolean isFileToLookIn(Path path) {
    File f = path.toFile();
    return f.isFile() && f.getName().endsWith(".html") && Character.isUpperCase(f.getName().charAt(0));
  }

  private static boolean containsString(final Path pathToFileToExamine, final String stringToLookForInRow1, 
                                        final String stringToLookForInRow2) {
    try {
      File fileToExamine = pathToFileToExamine.toFile();
      try(final BufferedReader reader = new BufferedReader(new FileReader(fileToExamine))) {
          String line;
          while ((line = reader.readLine()) != null) {
            if (line.contains(stringToLookForInRow1)) {
              if ((line = reader.readLine()) != null && line.contains(stringToLookForInRow2)) {
                return true;
              }
            }
          }          
        }
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    return false;          
  }
}

Sammanfattning av serien

Det har varit mycket lärorikt att skriva ihop den här lilla miniserien. Jag har verkligen lärt mig jättemycket, och jag tror även att jag kommer att komma ihåg sakerna bättre nu när jag skrivit om dem.

Angående själva innehållet i Java 8 så är jag imponerad av de delar som jag undersökt. Statiska- och defaultmetoder gör att det är lättare att utöka interface än vad det varit förrut. Tidigare har jag reflexmässigt nästan alltid skapat en abstrakt klass som implementerat ett interface och lagt denna mellan interfacet och den konkreta implementation. Detta behov minskar nu när man kan lägga till defaultmetoder både då interfacet skapas men även i efterhand.

De nya funktionella konstruktionerna i Java 8 är givetvis den största förändringen. Tycker att Oracle-folket fått till en riktig trevlig implementation av lambdas och closures. Det känns som om det hänger ihop på ett logiskt och bra sätt. Är det något man är osäker på syntaxtmässigt så kan man gissa "hur det borde vara" och ha en ganska hög sannolikhet att det man chansat på är rätt, vilket är ett bra betyg tycker jag.

Det känns även som om man fått in de funktionella förändringarna på alla ställen i JDK:n där de passar in; givetvis i collections-ramverket och Arrays men även i de klasser och paket som hanterar I/O (exempelvis i Files, se koden ovan). Det finns inget ställe som det är uppenbart att de missat att lägga till det funktionella stuffet.

Sammanfattningsvis har jag tyckt att det varit väldigt roligt att skriva den här lilla serien. Ser fram emot att skriva en liknande om Java 9 när nu den kommer ut. Hoppas det inte dröjer för länge!

Tidigare delar i serien

Del 1: Interface
Del 2: Streams och lambda expressions
Del 3: Metoder i Stream, metod- och konstruktorreferenser
Del 4: Metoder klassen Collectors
Del 5: Parallella strömmar
Del 6: Nyheter i Arrays

Referenser

[1] What's New in JDK 8


Leave a reply

Your name as it will be displayed when the comment is posted on the page. Your email address will not be published.