Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
cocktail d’expérience informatiques
             Genève 3 & 4 octobre 2011
                    Seconde édition
                      soft-shake.ch




Auteur    Julien PONGE
  Track   Java
Session   Java SE 7
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
Java SE 7
 Julien Ponge
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
Fork / Join

         Project Coin



                     NIO.2
              invokedynamic
                        (...)
Fork / Join
java.lang.Thread
     java.lang.Runnable

     wait()
<5   notify()
     synchronized
Thread thread = new Thread() {
   public void run() {
     System.out.println(">>> Hello!");
   }
};

thread.start();
thread.join();
java.util.concurrent

       executors
       concurrent queues
       concurrent collections
       atomic variables
5, 6   synchronization patterns
       rich locks
class Sum implements Callable<Long> {

    private final long from;
    private final long to;

    Sum(long from, long to) {
      this.from = from;
      this.to = to;
    }

    public Long call() {
      long acc = 0;
      for (long i = from; i <= to; i++) {
        acc = acc + i;
      }
      return acc;
    }
}
ExecutorService executor = Executors.newFixedThreadPool(2);

List<Future<Long>> results = executor.invokeAll(asList(
    new Sum(0, 10),
    new Sum(100, 1000),
    new Sum(10000, 1000000)
));

for (Future<Long> result : results) {
    System.out.println(result.get());
}
1.0   Threads made easy
1.1
1.2
1.3
1.4


 5    Concurrency made easier
 6



 7    Parallelism made easier
Sum of an array


n1   n2   n3   n4 n5   n6 n7     n8   n9     ...    ...     ...   ...


     sum1                 sum2               sum3
            sum1 + sum2                                   sum3 + (...)
                                 total sum
How many occurrences of
“java.util.List” in this filesystem tree?
Load into RAM (1 thread)

              Folder
                                         Document
 subfolders: List<Folder>
                             lines: List<String>
 documents: List<Document>




     Divide & conquer (#cores threads)
ForkJoinPool    Your work

Thread management      Split
Maximize parallelism   Fork subtasks
      Work stealing    Join subtasks
                       Compose results
ForkJoinTask




       join()                   join()
                                              RecursiveAction
                fork()    fork()
                                                     vs
                                               RecursiveTask

Child ForkJoinTask       Child ForkJoinTask
16


                          Folder word
                         counting task


 10
                                                         5
                                1


Document word      Document word              Folder word
 counting task      counting task            counting task



                                3                                 2

          fork()
                            Document word        Document word
  n       join()             counting task        counting task
(F/J demo)
Speedup&
7"

6"

5"

4"

3"

2"

1"
     2"   4"    6"   8"   10"   12"
                                      #cores
No I/O
No synchronization / locks

Decompose in simple recursive tasks
Do not decompose below a threshold

Take advantage of multicores with no pain

You have more F/J candidate algorithms than
you think!
try-with-resources
private void writeSomeData() throws IOException {
  DataOutputStream out = new DataOutputStream(new FileOutputStream("data"));
  out.writeInt(666);
  out.writeUTF("Hello");
  out.close();
}
private void writeSomeData() throws IOException {
  DataOutputStream out = new DataOutputStream(new FileOutputStream("data"));
  out.writeInt(666);
  out.writeUTF("Hello");
  out.close();
}


                                        what if...
private void writeSomeData() throws IOException {
  DataOutputStream out = null;
  try {
    out = new DataOutputStream(new FileOutputStream("data"));
    out.writeInt(666);
    out.writeUTF("Hello");
  } finally {
    if (out != null) {
      out.close();
    }
  }
}
private void writeSomeData() throws IOException {
  DataOutputStream out = null;
  try {
    out = new DataOutputStream(new FileOutputStream("data"));
    out.writeInt(666);
    out.writeUTF("Hello");
  } finally {
    if (out != null) {
      out.close();
    }
  }
}
                         ...this is still far from correct!
try (

    FileOutputStream out = new FileOutputStream("output");
    FileInputStream in1 = new FileInputStream(“input1”);
    FileInputStream in2 = new FileInputStream(“input2”)

) {

    // Do something useful with those 3 streams!
    // out, in1 and in2 will be closed in any case

    out.write(in1.read());
    out.write(in2.read());
}
public class AutoClose implements AutoCloseable {

    @Override
    public void close() {
      System.out.println(">>> close()");
      throw new RuntimeException("Exception in close()");
    }

    public void work() throws MyException {
      System.out.println(">>> work()");
      throw new MyException("Exception in work()");
    }
}
AutoClose autoClose = new AutoClose();
try {
  autoClose.work();
} finally {
  autoClose.close();
}
AutoClose autoClose = new AutoClose();
try {
  autoClose.work();
} finally {
  autoClose.close();
}



>>> work()
   >>> close()
   java.lang.RuntimeException: Exception in close()
          at AutoClose.close(AutoClose.java:6)
          at AutoClose.runWithMasking(AutoClose.java:19)
          at AutoClose.main(AutoClose.java:52)
AutoClose autoClose = new AutoClose();
try {
  autoClose.work();
} finally {
  autoClose.close();
}


            MyException
                        m   asked by Run
>>> work()                              time  Exception
   >>> close()
   java.lang.RuntimeException: Exception in close()
          at AutoClose.close(AutoClose.java:6)
          at AutoClose.runWithMasking(AutoClose.java:19)
          at AutoClose.main(AutoClose.java:52)
“Caused by” ≠ “Also happened”
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
  autoClose.work();
} catch (MyException e) {
  myException = e;
  throw e;
} finally {
  if (myException != null) {
    try {
      autoClose.close();
    } catch (Throwable t) {
      myException.addSuppressed(t);
    }
  } else {
    autoClose.close();
  }
}
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
  autoClose.work();
} catch (MyException e) {
  myException = e;
  throw e;
} finally {
  if (myException != null) {
    try {
      autoClose.close();
    } catch (Throwable t) {
      myException.addSuppressed(t);
    }
  } else {
    autoClose.close();
  }
}
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
  autoClose.work();
} catch (MyException e) {
  myException = e;
  throw e;
} finally {
  if (myException != null) {
    try {
      autoClose.close();
    } catch (Throwable t) {
      myException.addSuppressed(t);
    }
  } else {
    autoClose.close();
  }
}
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
  autoClose.work();
} catch (MyException e) {
  myException = e;
  throw e;
} finally {
  if (myException != null) {
    try {
      autoClose.close();
    } catch (Throwable t) {
      myException.addSuppressed(t);
    }
  } else {
    autoClose.close();
  }
}
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
  autoClose.work();
} catch (MyException e) {
  myException = e;
  throw e;
} finally {
  if (myException != null) {
    try {
      autoClose.close();
    } catch (Throwable t) {
      myException.addSuppressed(t);
    }
  } else {
    autoClose.close();
  }
}
try (AutoClose autoClose = new AutoClose()) {
  autoClose.work();
}
try (AutoClose autoClose = new AutoClose()) {
        autoClose.work();
      }



>>> work()
   >>> close()
   MyException: Exception in work()
          at AutoClose.work(AutoClose.java:11)
          at AutoClose.main(AutoClose.java:16)
          Suppressed: java.lang.RuntimeException: Exception in close()
                 at AutoClose.close(AutoClose.java:6)
                 at AutoClose.main(AutoClose.java:17)
public void compress(String input, String output)
             throws IOException {
  try(
    FileInputStream fin = new FileInputStream(input);
    FileOutputStream fout = new FileOutputStream(output);
    GZIPOutputStream out = new GZIPOutputStream(fout)
  ) {
    byte[] buffer = new byte[4096];
    int nread = 0;
    while ((nread = fin.read(buffer)) != -1) {
       out.write(buffer, 0, nread);
    }
  }
}
public void compress(String input, String output) throws IOException {   public void compress(String paramString1, String paramString2)
  try(                                                                              throws IOException {
    FileInputStream fin = new FileInputStream(input);                           FileInputStream localFileInputStream = new FileInputStream(paramString1);
    FileOutputStream fout = new FileOutputStream(output);                    Object localObject1 = null;
    GZIPOutputStream out = new GZIPOutputStream(fout)                           try {
  ) {                                                                               FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
    byte[] buffer = new byte[4096];                                              Object localObject2 = null;
    int nread = 0;                                                                  try {
    while ((nread = fin.read(buffer)) != -1) {                                          GZIPOutputStream localGZIPOutputStream = new GZIPOutputStream(localFileOutputStream);
       out.write(buffer, 0, nread);                                                  Object localObject3 = null;
    }                                                                                   try {
  }                                                                                         byte[] arrayOfByte = new byte[4096];
}                                                                                           int i = 0;
                                                                                            while ((i = localFileInputStream.read(arrayOfByte)) != -1) {
                                                                                                localGZIPOutputStream.write(arrayOfByte, 0, i);
                                                                                            }
                                                                                        } catch (Throwable localThrowable6) {
                                                                                            localObject3 = localThrowable6;
                                                                                            throw localThrowable6;
                                                                                        } finally {
                                                                                            if (localGZIPOutputStream != null) {
                                                                                                if (localObject3 != null) {
                                                                                                    try {
                                                                                                        localGZIPOutputStream.close();
                                                                                                    } catch (Throwable localThrowable7) {
                                                                                                        localObject3.addSuppressed(localThrowable7);
                                                                                                    }
                                                                                                } else {
                                                                                                    localGZIPOutputStream.close();
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    } catch (Throwable localThrowable4) {
                                                                                        localObject2 = localThrowable4;
                                                                                        throw localThrowable4;
                                                                                    } finally {
                                                                                        if (localFileOutputStream != null) {
                                                                                            if (localObject2 != null) {
                                                                                                try {
                                                                                                    localFileOutputStream.close();
                                                                                                } catch (Throwable localThrowable8) {
                                                                                                    localObject2.addSuppressed(localThrowable8);
                                                                                                }
                                                                                            } else {
                                                                                                localFileOutputStream.close();
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                } catch (Throwable localThrowable2) {
                                                                                    localObject1 = localThrowable2;
                                                                                    throw localThrowable2;
                                                                                } finally {
                                                                                    if (localFileInputStream != null) {
                                                                                        if (localObject1 != null) {
                                                                                            try {
                                                                                                localFileInputStream.close();
                                                                                            } catch (Throwable localThrowable9) {
                                                                                                localObject1.addSuppressed(localThrowable9);
                                                                                            }
                                                                                        } else {
                                                                                            localFileInputStream.close();
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
Not just syntactic sugar
Clutter-free, correct code

close():
   - be more specific than java.lang.Exception
   - no exception if it can’t fail
   - no exception that shall not be suppressed
       (e.g., java.lang.InterruptedException)
Diamond <>
List<String> strings = new LinkedList<Integer>();




Map<String, List<String>> contacts =
            new HashMap<Integer, String>();
List<String> strings = new LinkedList<String>();
strings.add("hello");
strings.add("world");

Map<String, List<String>> contacts = new HashMap<String, List<String>>();
contacts.put("Julien", new LinkedList<String>());
contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
List<String> strings = new LinkedList<>();
strings.add("hello");
strings.add("world");

Map<String, List<String>> contacts = new HashMap<>();
contacts.put("Julien", new LinkedList<String>());
contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
Map<String, String> map = new HashMap<String, String>() {
   {
     put("foo", "bar");
     put("bar", "baz");
   }
};
Map<String, String> map = new HashMap<>() {
   {
     put("foo", "bar");
     put("bar", "baz");
   }
};
Map<String, String> map = new HashMap<>() {
   {
     put("foo", "bar");
     put("bar", "baz");
   }
};


Diamond.java:43: error: cannot infer type arguments for HashMap;
        Map<String, String> map = new HashMap<>() {
                                              ^
  reason: cannot use '<>' with anonymous inner classes
1 error
class SomeClass<T extends Serializable & CharSequence> { }




                                     Non-denotable type
class SomeClass<T extends Serializable & CharSequence> { }




                                        Non-denotable type

SomeClass<?> foo = new SomeClass<String>();
SomeClass<?> fooInner = new SomeClass<String>() { };

SomeClass<?> bar = new SomeClass<>();

SomeClass<?> bar = new SomeClass<>() { };
class SomeClass<T extends Serializable & CharSequence> { }




                                        Non-denotable type

SomeClass<?> foo = new SomeClass<String>();
SomeClass<?> fooInner = new SomeClass<String>() { };

SomeClass<?> bar = new SomeClass<>();

SomeClass<?> bar = new SomeClass<>() { };




                                  No denotable type
                                  to generate a class
Less ceremony when using generics

No diamond with inner classes
Simplified varargs
private static <T> void doSomethingBad(List<T> list, T... values) {
    values[0] = list.get(0);
}

public static void main(String[] args) {
    List list = Arrays.asList("foo", "bar", "baz");
    doSomethingBad(list, 1, 2, 3);
}
This yields warnings + crash:
private static <T> void doSomethingBad(List<T> list, T... values) {
    values[0] = list.get(0);
}

public static void main(String[] args) {
    List list = Arrays.asList("foo", "bar", "baz");
    doSomethingBad(list, 1, 2, 3);
}
                           Heap Pollution: List = List<String>
private static <T> void doSomethingGood(List<T> list, T... values) {
    for (T value : values) {
        list.add(value);
    }
}
private static <T> void doSomethingGood(List<T> list, T... values) {
    for (T value : values) {
        list.add(value);
    }
}


$ javac Good.java
Note: Good.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
@SuppressWarnings({“unchecked”,“varargs”})
public static void main(String[] args) {
    List<String> list = new LinkedList<>();
    doSomethingGood(list, "hi", "there", "!");
}




$ javac Good.java
$
static, final methods, constructors



@SafeVarargs
private static <T> void doSomethingGood(List<T> list, T... values) {
    for (T value : values) {
        list.add(value);
    }
}
Mark your code as safe for varargs

You can’t cheat with @SafeVarags

Remove @SuppressWarnings in client code
and pay attention to real warnings
Multi-catch & more
 precise rethrow
Class<?> stringClass = Class.forName("java.lang.String");
Object instance = stringClass.newInstance();
Method toStringMethod = stringClass.getMethod("toString");
System.out.println(toStringMethod.invoke(instance));
try {
    Class<?> stringClass = Class.forName("java.lang.String");
    Object instance = stringClass.newInstance();
    Method toStringMethod = stringClass.getMethod("toString");
    System.out.println(toStringMethod.invoke(instance));
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
try {
    Class<?> stringClass = Class.forName("java.lang.String");
    Object instance = stringClass.newInstance();
    Method toStringMethod = stringClass.getMethod("toString");
    System.out.println(toStringMethod.invoke(instance));
} catch (Throwable t) {
    t.printStackTrace();
}
try {
    Class<?> stringClass = Class.forName("java.lang.String");
    Object instance = stringClass.newInstance();
    Method toStringMethod = stringClass.getMethod("toString");
    System.out.println(toStringMethod.invoke(instance));
} catch (Throwable t) {
    t.printStackTrace();
}




                           How about SecurityException?
try {
    Class<?> stringClass = Class.forName("java.lang.String");
    Object instance = stringClass.newInstance();
    Method toStringMethod = stringClass.getMethod("toString");
    System.out.println(toStringMethod.invoke(instance));
} catch (ClassNotFoundException | InstantiationException |
         IllegalAccessException | NoSuchMethodException |
         InvocationTargetException e) {
    e.printStackTrace();
}




                           Union of alternatives
catch (SomeException e)




Now implicitly final unless assigned...
static class SomeRootException extends Exception { }
static class SomeChildException extends SomeRootException { }
static class SomeOtherChildException extends SomeRootException { }

public static void main(String... args) throws Throwable {
try {
    throw new SomeChildException();
} catch (SomeRootException firstException) {
    try {
        throw firstException;
    } catch (SomeOtherChildException secondException) {
        System.out.println("I got you!");
    }
}
static class SomeRootException extends Exception { }
static class SomeChildException extends SomeRootException { }
static class SomeOtherChildException extends SomeRootException { }

public static void main(String... args) throws Throwable {
try {
    throw new SomeChildException();
} catch (SomeRootException firstException) {
    try {
        throw firstException;
    } catch (SomeOtherChildException secondException) {
        System.out.println("I got you!");
    }
}


$ javac Imprecise.java
Imprecise.java:13: error: exception SomeOtherChildException is never thrown in body of
corresponding try statement
            } catch (SomeOtherChildException secondException) {
              ^
1 error
Less clutter
Be precise
Do not capture unintended exceptions

Better exception flow analysis
Minor additions
// 123 in decimal, octal, hexadecimal and binary
byte decimal = 123;
byte octal = 0_173;
byte hexadecimal = 0x7b;
byte binary = 0b0111_1011;

// Other values
double doubleValue = 1.111_222_444F;
long longValue = 1_234_567_898L;
long longHexa = 0x1234_3b3b_0123_cdefL;
public static boolean isTrue(String str) {
    switch(str.trim().toUpperCase()) {
        case "OK":
        case "YES":
        case "TRUE":
            return true;

        case "KO":
        case "NO":
        case "FALSE":
            return false;

        default:
            throw new IllegalArgumentException("Not a valid true/false string.");
    }
}
public static boolean isTrue(String s) {
    String str = s.trim().toUpperCase();
    int jump = -1;
    switch(str.hashCode()) {
        case 2404:
            if (str.equals("KO")) {
                 jump = 3;                        Bucket
            }
            break;
(...)
    switch(jump) {
(...)
        case 3:
        case 4:
        case 5:
            return false;
        default:                                           Real code
            throw new IllegalArgumentException(
        "Not a valid true/false string.");
    }
}
Oracle Technology Network (more soon...)


           Fork and Join: Java Can Excel at
         Painless Parallel Programming Too!
                            http://goo.gl/tostz



           Better Resource Management with
          Java SE 7: Beyond Syntactic Sugar
                           http://goo.gl/7ybgr
Julien Ponge
                 @jponge

  http://gplus.to/jponge

http://julien.ponge.info/

julien.ponge@insa-lyon.fr

More Related Content

soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin

  • 1. cocktail d’expérience informatiques Genève 3 & 4 octobre 2011 Seconde édition soft-shake.ch Auteur Julien PONGE Track Java Session Java SE 7
  • 3. Java SE 7 Julien Ponge
  • 5. Fork / Join Project Coin NIO.2 invokedynamic (...)
  • 7. java.lang.Thread java.lang.Runnable wait() <5 notify() synchronized
  • 8. Thread thread = new Thread() { public void run() { System.out.println(">>> Hello!"); } }; thread.start(); thread.join();
  • 9. java.util.concurrent executors concurrent queues concurrent collections atomic variables 5, 6 synchronization patterns rich locks
  • 10. class Sum implements Callable<Long> { private final long from; private final long to; Sum(long from, long to) { this.from = from; this.to = to; } public Long call() { long acc = 0; for (long i = from; i <= to; i++) { acc = acc + i; } return acc; } }
  • 11. ExecutorService executor = Executors.newFixedThreadPool(2); List<Future<Long>> results = executor.invokeAll(asList( new Sum(0, 10), new Sum(100, 1000), new Sum(10000, 1000000) )); for (Future<Long> result : results) { System.out.println(result.get()); }
  • 12. 1.0 Threads made easy 1.1 1.2 1.3 1.4 5 Concurrency made easier 6 7 Parallelism made easier
  • 13. Sum of an array n1 n2 n3 n4 n5 n6 n7 n8 n9 ... ... ... ... sum1 sum2 sum3 sum1 + sum2 sum3 + (...) total sum
  • 14. How many occurrences of “java.util.List” in this filesystem tree?
  • 15. Load into RAM (1 thread) Folder Document subfolders: List<Folder> lines: List<String> documents: List<Document> Divide & conquer (#cores threads)
  • 16. ForkJoinPool Your work Thread management Split Maximize parallelism Fork subtasks Work stealing Join subtasks Compose results
  • 17. ForkJoinTask join() join() RecursiveAction fork() fork() vs RecursiveTask Child ForkJoinTask Child ForkJoinTask
  • 18. 16 Folder word counting task 10 5 1 Document word Document word Folder word counting task counting task counting task 3 2 fork() Document word Document word n join() counting task counting task
  • 20. Speedup& 7" 6" 5" 4" 3" 2" 1" 2" 4" 6" 8" 10" 12" #cores
  • 21. No I/O No synchronization / locks Decompose in simple recursive tasks Do not decompose below a threshold Take advantage of multicores with no pain You have more F/J candidate algorithms than you think!
  • 23. private void writeSomeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); out.close(); }
  • 24. private void writeSomeData() throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); out.close(); } what if...
  • 25. private void writeSomeData() throws IOException { DataOutputStream out = null; try { out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); } finally { if (out != null) { out.close(); } } }
  • 26. private void writeSomeData() throws IOException { DataOutputStream out = null; try { out = new DataOutputStream(new FileOutputStream("data")); out.writeInt(666); out.writeUTF("Hello"); } finally { if (out != null) { out.close(); } } } ...this is still far from correct!
  • 27. try ( FileOutputStream out = new FileOutputStream("output"); FileInputStream in1 = new FileInputStream(“input1”); FileInputStream in2 = new FileInputStream(“input2”) ) { // Do something useful with those 3 streams! // out, in1 and in2 will be closed in any case out.write(in1.read()); out.write(in2.read()); }
  • 28. public class AutoClose implements AutoCloseable { @Override public void close() { System.out.println(">>> close()"); throw new RuntimeException("Exception in close()"); } public void work() throws MyException { System.out.println(">>> work()"); throw new MyException("Exception in work()"); } }
  • 29. AutoClose autoClose = new AutoClose(); try { autoClose.work(); } finally { autoClose.close(); }
  • 30. AutoClose autoClose = new AutoClose(); try { autoClose.work(); } finally { autoClose.close(); } >>> work() >>> close() java.lang.RuntimeException: Exception in close()        at AutoClose.close(AutoClose.java:6)        at AutoClose.runWithMasking(AutoClose.java:19)        at AutoClose.main(AutoClose.java:52)
  • 31. AutoClose autoClose = new AutoClose(); try { autoClose.work(); } finally { autoClose.close(); } MyException m asked by Run >>> work() time Exception >>> close() java.lang.RuntimeException: Exception in close()        at AutoClose.close(AutoClose.java:6)        at AutoClose.runWithMasking(AutoClose.java:19)        at AutoClose.main(AutoClose.java:52)
  • 32. “Caused by” ≠ “Also happened”
  • 33. AutoClose autoClose = new AutoClose(); MyException myException = null; try { autoClose.work(); } catch (MyException e) { myException = e; throw e; } finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); } }
  • 34. AutoClose autoClose = new AutoClose(); MyException myException = null; try { autoClose.work(); } catch (MyException e) { myException = e; throw e; } finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); } }
  • 35. AutoClose autoClose = new AutoClose(); MyException myException = null; try { autoClose.work(); } catch (MyException e) { myException = e; throw e; } finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); } }
  • 36. AutoClose autoClose = new AutoClose(); MyException myException = null; try { autoClose.work(); } catch (MyException e) { myException = e; throw e; } finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); } }
  • 37. AutoClose autoClose = new AutoClose(); MyException myException = null; try { autoClose.work(); } catch (MyException e) { myException = e; throw e; } finally { if (myException != null) { try { autoClose.close(); } catch (Throwable t) { myException.addSuppressed(t); } } else { autoClose.close(); } }
  • 38. try (AutoClose autoClose = new AutoClose()) { autoClose.work(); }
  • 39. try (AutoClose autoClose = new AutoClose()) { autoClose.work(); } >>> work() >>> close() MyException: Exception in work()        at AutoClose.work(AutoClose.java:11)        at AutoClose.main(AutoClose.java:16)        Suppressed: java.lang.RuntimeException: Exception in close()               at AutoClose.close(AutoClose.java:6)               at AutoClose.main(AutoClose.java:17)
  • 40. public void compress(String input, String output) throws IOException { try( FileInputStream fin = new FileInputStream(input); FileOutputStream fout = new FileOutputStream(output); GZIPOutputStream out = new GZIPOutputStream(fout) ) { byte[] buffer = new byte[4096]; int nread = 0; while ((nread = fin.read(buffer)) != -1) { out.write(buffer, 0, nread); } } }
  • 41. public void compress(String input, String output) throws IOException { public void compress(String paramString1, String paramString2) try(         throws IOException { FileInputStream fin = new FileInputStream(input);     FileInputStream localFileInputStream = new FileInputStream(paramString1); FileOutputStream fout = new FileOutputStream(output);     Object localObject1 = null; GZIPOutputStream out = new GZIPOutputStream(fout)     try { ) {         FileOutputStream localFileOutputStream = new FileOutputStream(paramString2); byte[] buffer = new byte[4096];         Object localObject2 = null; int nread = 0;         try { while ((nread = fin.read(buffer)) != -1) {             GZIPOutputStream localGZIPOutputStream = new GZIPOutputStream(localFileOutputStream); out.write(buffer, 0, nread);             Object localObject3 = null; }             try { }                 byte[] arrayOfByte = new byte[4096]; }                 int i = 0;                 while ((i = localFileInputStream.read(arrayOfByte)) != -1) {                     localGZIPOutputStream.write(arrayOfByte, 0, i);                 }             } catch (Throwable localThrowable6) {                 localObject3 = localThrowable6;                 throw localThrowable6;             } finally {                 if (localGZIPOutputStream != null) {                     if (localObject3 != null) {                         try {                             localGZIPOutputStream.close();                         } catch (Throwable localThrowable7) {                             localObject3.addSuppressed(localThrowable7);                         }                     } else {                         localGZIPOutputStream.close();                     }                 }             }         } catch (Throwable localThrowable4) {             localObject2 = localThrowable4;             throw localThrowable4;         } finally {             if (localFileOutputStream != null) {                 if (localObject2 != null) {                     try {                         localFileOutputStream.close();                     } catch (Throwable localThrowable8) {                         localObject2.addSuppressed(localThrowable8);                     }                 } else {                     localFileOutputStream.close();                 }             }         }     } catch (Throwable localThrowable2) {         localObject1 = localThrowable2;         throw localThrowable2;     } finally {         if (localFileInputStream != null) {             if (localObject1 != null) {                 try {                     localFileInputStream.close();                 } catch (Throwable localThrowable9) {                     localObject1.addSuppressed(localThrowable9);                 }             } else {                 localFileInputStream.close();             }         }     } }
  • 42. Not just syntactic sugar Clutter-free, correct code close(): - be more specific than java.lang.Exception - no exception if it can’t fail - no exception that shall not be suppressed (e.g., java.lang.InterruptedException)
  • 44. List<String> strings = new LinkedList<Integer>(); Map<String, List<String>> contacts = new HashMap<Integer, String>();
  • 45. List<String> strings = new LinkedList<String>(); strings.add("hello"); strings.add("world"); Map<String, List<String>> contacts = new HashMap<String, List<String>>(); contacts.put("Julien", new LinkedList<String>()); contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
  • 46. List<String> strings = new LinkedList<>(); strings.add("hello"); strings.add("world"); Map<String, List<String>> contacts = new HashMap<>(); contacts.put("Julien", new LinkedList<String>()); contacts.get("Julien").addAll(asList("Foo", "Bar", "Baz"));
  • 47. Map<String, String> map = new HashMap<String, String>() { { put("foo", "bar"); put("bar", "baz"); } };
  • 48. Map<String, String> map = new HashMap<>() { { put("foo", "bar"); put("bar", "baz"); } };
  • 49. Map<String, String> map = new HashMap<>() { { put("foo", "bar"); put("bar", "baz"); } }; Diamond.java:43: error: cannot infer type arguments for HashMap; Map<String, String> map = new HashMap<>() { ^ reason: cannot use '<>' with anonymous inner classes 1 error
  • 50. class SomeClass<T extends Serializable & CharSequence> { } Non-denotable type
  • 51. class SomeClass<T extends Serializable & CharSequence> { } Non-denotable type SomeClass<?> foo = new SomeClass<String>(); SomeClass<?> fooInner = new SomeClass<String>() { }; SomeClass<?> bar = new SomeClass<>(); SomeClass<?> bar = new SomeClass<>() { };
  • 52. class SomeClass<T extends Serializable & CharSequence> { } Non-denotable type SomeClass<?> foo = new SomeClass<String>(); SomeClass<?> fooInner = new SomeClass<String>() { }; SomeClass<?> bar = new SomeClass<>(); SomeClass<?> bar = new SomeClass<>() { }; No denotable type to generate a class
  • 53. Less ceremony when using generics No diamond with inner classes
  • 55. private static <T> void doSomethingBad(List<T> list, T... values) { values[0] = list.get(0); } public static void main(String[] args) { List list = Arrays.asList("foo", "bar", "baz"); doSomethingBad(list, 1, 2, 3); }
  • 56. This yields warnings + crash: private static <T> void doSomethingBad(List<T> list, T... values) { values[0] = list.get(0); } public static void main(String[] args) { List list = Arrays.asList("foo", "bar", "baz"); doSomethingBad(list, 1, 2, 3); } Heap Pollution: List = List<String>
  • 57. private static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); } }
  • 58. private static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); } } $ javac Good.java Note: Good.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
  • 59. @SuppressWarnings({“unchecked”,“varargs”}) public static void main(String[] args) { List<String> list = new LinkedList<>(); doSomethingGood(list, "hi", "there", "!"); } $ javac Good.java $
  • 60. static, final methods, constructors @SafeVarargs private static <T> void doSomethingGood(List<T> list, T... values) { for (T value : values) { list.add(value); } }
  • 61. Mark your code as safe for varargs You can’t cheat with @SafeVarags Remove @SuppressWarnings in client code and pay attention to real warnings
  • 62. Multi-catch & more precise rethrow
  • 63. Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance));
  • 64. try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
  • 65. try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance)); } catch (Throwable t) { t.printStackTrace(); }
  • 66. try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance)); } catch (Throwable t) { t.printStackTrace(); } How about SecurityException?
  • 67. try { Class<?> stringClass = Class.forName("java.lang.String"); Object instance = stringClass.newInstance(); Method toStringMethod = stringClass.getMethod("toString"); System.out.println(toStringMethod.invoke(instance)); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } Union of alternatives
  • 68. catch (SomeException e) Now implicitly final unless assigned...
  • 69. static class SomeRootException extends Exception { } static class SomeChildException extends SomeRootException { } static class SomeOtherChildException extends SomeRootException { } public static void main(String... args) throws Throwable { try { throw new SomeChildException(); } catch (SomeRootException firstException) { try { throw firstException; } catch (SomeOtherChildException secondException) { System.out.println("I got you!"); } }
  • 70. static class SomeRootException extends Exception { } static class SomeChildException extends SomeRootException { } static class SomeOtherChildException extends SomeRootException { } public static void main(String... args) throws Throwable { try { throw new SomeChildException(); } catch (SomeRootException firstException) { try { throw firstException; } catch (SomeOtherChildException secondException) { System.out.println("I got you!"); } } $ javac Imprecise.java Imprecise.java:13: error: exception SomeOtherChildException is never thrown in body of corresponding try statement } catch (SomeOtherChildException secondException) { ^ 1 error
  • 71. Less clutter Be precise Do not capture unintended exceptions Better exception flow analysis
  • 73. // 123 in decimal, octal, hexadecimal and binary byte decimal = 123; byte octal = 0_173; byte hexadecimal = 0x7b; byte binary = 0b0111_1011; // Other values double doubleValue = 1.111_222_444F; long longValue = 1_234_567_898L; long longHexa = 0x1234_3b3b_0123_cdefL;
  • 74. public static boolean isTrue(String str) { switch(str.trim().toUpperCase()) { case "OK": case "YES": case "TRUE": return true; case "KO": case "NO": case "FALSE": return false; default: throw new IllegalArgumentException("Not a valid true/false string."); } }
  • 75. public static boolean isTrue(String s) { String str = s.trim().toUpperCase(); int jump = -1; switch(str.hashCode()) { case 2404: if (str.equals("KO")) { jump = 3; Bucket } break; (...) switch(jump) { (...) case 3: case 4: case 5: return false; default: Real code throw new IllegalArgumentException( "Not a valid true/false string."); } }
  • 76. Oracle Technology Network (more soon...) Fork and Join: Java Can Excel at Painless Parallel Programming Too! http://goo.gl/tostz Better Resource Management with Java SE 7: Beyond Syntactic Sugar http://goo.gl/7ybgr
  • 77. Julien Ponge @jponge http://gplus.to/jponge http://julien.ponge.info/ julien.ponge@insa-lyon.fr