Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017

1,049 views

Published on

When Java 8 hit the streets, a lot of people were either excited or confused about the two biggest language changes that were introduced: lambdas and streams. While these two things might seem to be “just another syntax” for doing what we can already do, it turns out that these two programming techniques are very powerful because of the WAY they work. Even if you’re not using Java 8 just yet, this session will show you the potential of using these new language features.

A presentation by Julian Robichaux (panagenda)

Published in: Software
  • Be the first to comment

DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017

  1. 1. DEV-1550: Why Java 8? Or, What's a Lambda? Julian Robichaux, panagenda
  2. 2. Who am I? • Julian Robichaux – Programmer and product manager at panagenda – Developing applications using IBM products since mid-90’s – Several open-source projects on OpenNTF – “Learn Java by Example” video course 
 on lynda.com (LinkedIn Learning) – IBM Champion since 2011 – nsftools.com (old stuff) – @jrobichaux 2
  3. 3. Why are we here? • To talk about Java 8! – specifically lambdas and streams – syntax, gotchas, and “why change?”
 
 • Assuming that everyone in the room is a Java programmer – you don’t have to be an expert – any version is fine, we will start with Java 6 – we will also touch on Java 7, just in case
 
 • What to do if you’re still on a Java 6 platform 3
  4. 4. Example Code • Connect to a web server via HTTPS, and report the key size and expiration date of the SSL certificate – check servers for vulnerabilities due to old/weak keys – tell your admins it’s time to renew the certificate 4 URL url = new URL( "https://my.server" ); checkSSLCertificate(url);
  5. 5. public static void checkSSLCertificate(URL url) { HttpsURLConnection con = null; try { con = (HttpsURLConnection) url.openConnection(); con.setSSLSocketFactory( fakeSocketFactory() ); con.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; // trust everyone! } }); con.connect(); Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { System.out.println( "Valid until: " + ((X509Certificate)cert).getNotAfter()); System.out.println( "Server key bit length: " + ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ); } } catch (IOException e) { e.printStackTrace(); } catch (GeneralSecurityException e) { e.printStackTrace(); } finally { con.disconnect(); } } Example Code (Java 6) create an HTTPS connection tell it that self-signed and expired certificates are okay report the expiration date and RSA key length of each SSL certificate on the server Exception handling!
  6. 6. Example Code (Java 6) /** * Creates an SSLSocketFactory that doesn't check certificates at all * DO NOT USE THIS IN REAL LIFE */ private static SSLSocketFactory fakeSocketFactory() throws GeneralSecurityException { TrustManager trustEveryone = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[] { trustEveryone }, new SecureRandom()); return sslContext.getSocketFactory(); }
  7. 7. A Few Words About Java 7 because you’ll see this stuff in Java 8
  8. 8. Catch Multiple Exceptions • Try-catch blocks can catch multiple exceptions in one statement HttpsURLConnection con = null; try { con = (HttpsURLConnection) url.openConnection(); // do stuff.. } catch (IOException e) { e.printStackTrace(); } catch (GeneralSecurityException e) { e.printStackTrace(); } finally { con.disconnect(); } HttpsURLConnection con = null; try { con = (HttpsURLConnection) url.openConnection(); // do stuff.. } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } finally { con.disconnect(); }
  9. 9. Try-with-resources • Classes that implement the AutoCloseable interface can be automatically closed by a try-catch block HttpsURLConnection con = null; try { con = (HttpsURLConnection) url.openConnection(); // do stuff.. } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } finally { con.disconnect(); } try (CloseableURLConnection closeableCon = new CloseableURLConnection(url)) { HttpsURLConnection con = closeableCon.getHttpsConnection(); // do stuff.. } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } * * *
  10. 10. Creating a Closeable Class static class CloseableURLConnection implements AutoCloseable { URLConnection con; public CloseableURLConnection(URL url) throws IOException { con = url.openConnection(); } public HttpsURLConnection getHttpsConnection() { return (HttpsURLConnection)con; } @Override public void close() { getHttpsConnection().disconnect(); } } implement AutoCloseable create a close() method
  11. 11. Closeable Classes • Several standard Java classes are now AutoClosable – InputStream – OutputStream – Reader – Writer – java.sql.Connection, Statement, and ResultSet
 • You no longer have to declare your streams outside the try/catch block, or remember to close them when you’re done!
 • Like a finally clause, try-with-resources objects get closed even if an Exception is thrown 11
  12. 12. A Few Other Java 7 Goodies • New and/or improved classes – java.nio.file, updated XML libraries, new/enhanced cryptography providers
 • Binary literals and underscores in numeric literals – int byteNum = 0b00100001; – int phoneNum = 555_1212;
 • Type inference for generics – Map<String, List<String>> map = new HashMap<>();
 • Switch statements operate on Strings
 • http://docs.oracle.com/javase/8/docs/technotes/guides/language/enhancements.html 
 http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
  13. 13. And Now: Java 8 on to the good stuff
  14. 14. The Code in Java 7… public static void checkSSLCertificate(URL url) { try (CloseableURLConnection closeableCon = new CloseableURLConnection(url)) { HttpsURLConnection con = closeableCon.getHttpsConnection(); con.setSSLSocketFactory( fakeSocketFactory() ); con.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; // trust everyone! } }); con.connect(); Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { System.out.println( "Valid until: " + ((X509Certificate)cert).getNotAfter()); System.out.println( "Server key bit length: " + ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ); } } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } } anonymous class loop through an array
  15. 15. The Code in Java 8 public static void checkSSLCertificate(URL url) { try (CloseableURLConnection closeableCon = new CloseableURLConnection(url)) { HttpsURLConnection con = closeableCon.getHttpsConnection(); con.setSSLSocketFactory( fakeSocketFactory() ); con.setHostnameVerifier( (hostname, session) -> true ); con.connect(); Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } } lambda hostname verifier read the array as a stream, not a loop
  16. 16. What’s a Lambda? • Simplified syntax for writing single-method classes
 • You are effectively passing a function as a parameter to a method 16 con.setHostnameVerifier( (hostname, session) -> true ); (parameters) arrow expression
  17. 17. How Does that Lambda Work? con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); ?
  18. 18. How Does that Lambda Work? con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); ?
  19. 19. How Does that Lambda Work? con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); ?
  20. 20. How Does that Lambda Work? con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); ?
  21. 21. How Does that Lambda Work? con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); !
  22. 22. Functional Interfaces • Lambdas rely on “functional interfaces” to work – an interface with only one abstract method – also called a “single abstract method” or SAM interface – there can be only one! <insert highlander joke here>
 • If there’s only one method, the compiler knows which one you will call
 • If you know the method, and the compiler knows the method, we don’t have to talk about the method – everyone already knows! – skip the obvious stuff 22
  23. 23. Functional Interfaces con.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); con.setHostnameVerifier( (hostname, session) -> true ); the class MUST be a HostnameVerifier, and the method MUST be verify(String, SSLSession) therefore… throw away everything obvious
  24. 24. Lambda Syntax object.method( (param1, param2) -> result ); object.method( param1 -> doStuff(param1) ); object.method( param1 -> doStuff(param1, object) ); object.method( () -> { doStuff(); return doMoreStuff(); } );
  25. 25. Method References • There is an alternative syntax called “Method References” – for a lambda that only calls a single method of the parameter, or a single static method that uses the parameter, or creates a single new Object object.method( s -> s.getLength() ); object.method( String::getLength ); http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
  26. 26. Another Example: Sandwiches! static enum Sandwich { PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); private String name; private int calories; private Sandwich(String name, int calories) { this.name = name; this.calories = calories; } public String getName() { return name; } public int getCalories() { return calories; } public String toString() { return "n" + calories + " caloriest" + name; } }
  27. 27. List the Sandwiches in Order of Calories List<Sandwich> sandwiches = Arrays.asList( Sandwich.values() ); Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); System.out.println(sandwiches); PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); 500 calories Peanut butter & jelly, 500 calories Sub, 500 calories Taco, 900 calories Hot dog, 900 calories Pizza
  28. 28. List the Sandwiches in Order of Calories List<Sandwich> sandwiches = Arrays.asList( Sandwich.values() ); /* Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); */ Collections.sort(sandwiches, (s1, s2) -> Integer.compare(s1.getCalories(), s2.getCalories()) ); System.out.println(sandwiches); PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); 500 calories Peanut butter & jelly, 500 calories Sub, 500 calories Taco, 900 calories Hot dog, 900 calories Pizza
  29. 29. List the Sandwiches in Order of Calories List<Sandwich> sandwiches = Arrays.asList( Sandwich.values() ); /* Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); */ Collections.sort(sandwiches, Comparator.comparing( sandwich -> sandwich.getCalories() ) ); System.out.println(sandwiches); PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); 500 calories Peanut butter & jelly, 500 calories Sub, 500 calories Taco, 900 calories Hot dog, 900 calories Pizza
  30. 30. List the Sandwiches in Order of Calories List<Sandwich> sandwiches = Arrays.asList( Sandwich.values() ); /* Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); */ Collections.sort(sandwiches, Comparator.comparing( Sandwich::getCalories ) ); System.out.println(sandwiches); PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); 500 calories Peanut butter & jelly, 500 calories Sub, 500 calories Taco, 900 calories Hot dog, 900 calories Pizza
  31. 31. All These are the Same Comparator Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); Collections.sort(sandwiches, (s1, s2) -> Integer.compare(s1.getCalories(), s2.getCalories()) ); Collections.sort(sandwiches, Comparator.comparing( sandwich -> sandwich.getCalories() ) ); Collections.sort(sandwiches, Comparator.comparing( Sandwich::getCalories ) );
  32. 32. Fun with the Comparator Collections.sort(sandwiches, Comparator.comparing( Sandwich::getCalories ) .thenComparing( Sandwich::getName ) .reversed() ); 900 calories Pizza, 900 calories Hot dog, 500 calories Taco, 500 calories Sub, 500 calories Peanut butter & jelly PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900);
  33. 33. But Really, What’s the Point? • This all seems like needless tomfoolery – after all, the old code still works!
 • Two major advantages: 1. Forces (or strongly encourages) you to write functional code 2. Less visual noise makes code easier to read and understand 33 Collections.sort(sandwiches, new Comparator<Sandwich>() { public int compare(Sandwich s1, Sandwich s2) { return Integer.compare(s1.getCalories(), s2.getCalories()); } }); Collections.sort(sandwiches, Comparator.comparing( Sandwich::getCalories ) );
  34. 34. Code Should Describe Behavior Code Should Read Like A Story
  35. 35. Dealing with Exceptions Collections.sort(sandwiches, Comparator.comparing( Sandwich::getCalories ) .thenComparing( Sandwich::getName ) .reversed() ); NULLWICH (null, 500), PB_J ("Peanut butter & jelly", 500), SUB ("Sub", 500), HOTDOG ("Hot dog", 900), TACO ("Taco", 500), PIZZA ("Pizza", 900); Exception in thread "main" java.lang.NullPointerException at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:217) at java.util.Collections$ReverseComparator2.compare(Collections.java:5178) at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) at java.util.TimSort.sort(TimSort.java:220) at java.util.Arrays.sort(Arrays.java:1438) at java.util.Arrays$ArrayList.sort(Arrays.java:3895) at java.util.Collections.sort(Collections.java:175) at com.panagenda.ssltest.MoreJava8Examples.main(MoreJava8Examples.java:52)
  36. 36. Dealing with Exceptions • It’s not always obvious what caused the Exception
 • It’s cumbersome to add a try/catch to a lambda – same with adding logging
 • If an Exception is possible, maybe better to call out to a method instead 36 Collections.sort(sandwiches, Comparator.comparing( sandwich -> getCalories(sandwich) ) .thenComparing( sandwich -> getName(sandwich) ) .reversed() );
  37. 37. A Few More Examples // process all the keys and values of a HashMap Map<String, Integer> myHashMap = new HashMap<>(); myHashMap.forEach( (key, value) -> System.out.println(key + "; " + value) ); // remove all the null elements in a List List<String> myArrayList = new ArrayList<>(); myArrayList.removeIf( s -> s == null ); // get all the JPG files in a directory File photoDir = new File("c:/photos"); File[] docFiles = photoDir.listFiles( file -> file.getName().endsWith("jpg") ); // run some code in a thread new Thread( () -> doSomething() ).start();
  38. 38. Under the Hood • If you’re really curious about how all this works… – http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html 
 • It’s all Function and Predicate objects – https://docs.oracle.com/javase/8/docs/api/java/util/function/package- summary.html – Closures? By some definitions. 38 Function<Sandwich, Integer> caloryCompare = sandwich -> sandwich.getCalories();
  39. 39. Streams! of data, not water
  40. 40. From Loop to Stream Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { System.out.println( "Valid until: " + ((X509Certificate)cert).getNotAfter()); System.out.println( "Server key bit length: " + ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ); } Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); ?
  41. 41. What Does that Loop Actually Do? 41 Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { System.out.println( "Valid until: " + ((X509Certificate)cert).getNotAfter()); System.out.println( "Server key bit length: " + ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ); } print the information get something from the objectprint the information get something from the object
  42. 42. How Does the Stream Work? Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); start with an array, convert it to a List convert the List to a stream TIP: this could also be just Arrays.stream(certs) } change the stream do something to each item change the stream do something to each item
  43. 43. Breaking Down the Example Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); map() converts each item by casting it to X509Certificate, then returns a Stream of X509Certificate objects map() gets an int value from each item, then returns a Stream of int values start with an array of Certificates
  44. 44. Breaking Down the Example Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); peek() is an intermediate operation: it does something with each item and returns the original Stream forEach() is a terminal operation: it does something with each item and stops
  45. 45. What’s a Stream? • Allows you to perform operations on a collection of data – multiple operations can be combined in a pipeline
 
 • Has the following properties – uses functional arguments (lambdas!) to process data – does not store data – pipeline operations are optimized for laziness – optionally process in parallel (multi-threaded) with no extra code 45
  46. 46. Is a Stream Better than a Loop? Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { System.out.println( "Valid until: " + ((X509Certificate)cert).getNotAfter()); System.out.println( "Server key bit length: " + ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ); } Certificate[] certs = con.getServerCertificates(); Arrays.asList(certs) .stream() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); !Stream version is more descriptive of the behavior of the code Stream version can easily be turned into multi-threaded code
  47. 47. Multi-threaded You Say? Arrays.asList(certs) .stream() .parallel() .map ( cert -> (X509Certificate)cert ) .peek( cert -> System.out.println("Valid until: " + cert.getNotAfter()) ) .map ( cert -> ((RSAPublicKey)cert.getPublicKey()).getModulus().bitLength() ) .forEach( i -> System.out.println("Server key bit length: " + i) ); DANGER: The forEach() and peek() output might be out-of-order!
  48. 48. Adding Numbers in a Loop 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 45 int sum = 0; for (int i : new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}) { sum += i; } return sum;
  49. 49. Adding Numbers with Reduce 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 1 + 2 3 + 4 + 5 6 + 8 7 + 9 3 + 14 12 + 16 45
  50. 50. Adding Numbers with Reduce 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 1 + 2 3 + 4 + 5 6 + 8 7 + 9 3 + 14 12 + 16 45 By abstracting away the very concept of looping, you can implement looping any way you want, including implementing it in a way that scales nicely with extra hardware. Joel Spolsky https://www.joelonsoftware.com/2006/08/01/ can-your-programming-language-do-this each computation could be on a separate processor core… or a separate machine!
  51. 51. Other Things to Know About Streams • Normally get them from Collections or arrays – List.stream(), Map.entrySet().stream(), Arrays.stream(Object[]) – also other fun places, like BufferedReader.lines() or Files.list()
 
 • Some operations will short circuit instead of processing each item – built-in optimizations
 
 • Stream operations should be stateless – for example, don’t update Lists as part of a stream operation – items could process out of order, and might not be thread-safe – collect the results at the end instead 51
  52. 52. Other Things to Know About Streams • Operations on Streams should be associative when possible – (a + b + c) == (c + b + a) == b + (a + c) – if order of operations does matter, make sure you: • start with an ordered set of data, like a List • use forEachOrdered() instead of forEach() • don’t use reduce() 
 
 • For reference: – https://docs.oracle.com/javase/8/docs/api/java/util/stream/package- summary.html 52
  53. 53. Under the Hood • If you’re really curious about how all this works… – http://www.ibm.com/developerworks/java/library/j-java-streams-1-brian- goetz 
 • Read about java.util.function – https://docs.oracle.com/javase/8/docs/api/java/util/function/package- summary.html – Predicate, Consumer, and Supplier interfaces 53
  54. 54. Backwards Compatibility because not all of us have a choice
  55. 55. Java 8 API Changes (partial list) • Streams – in its own package – throughout Collections, Files, etc.
 • Functional classes in java.util.function
 • Brand new Date-Time package and classes – http://docs.oracle.com/javase/tutorial/datetime 
 • JavaFX for GUIs
 • http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html 
 http://docs.oracle.com/javase/8/docs/technotes/guides/language/lambda_api_jdk8.html 55 Function<Sandwich, Integer> caloryCompare = sandwich -> sandwich.getCalories();
  56. 56. Compiling to Earlier Versions • Java can compile for previous versions, but… – you can’t use any of the new APIs (classes or methods) – you can’t use any of the new language features
 
 • What happens if you use a Java 8 JAR in a Java 6 environment? – it won’t work – the JRE checks the JAR file for a version number first – if the version number is too high, you get errors
 
 • Some tools can convert bytecode to earlier versions – but new APIs still won’t work 56
  57. 57. Options for Backwards Compatibility • If you don’t want to use new language features at all – set “Source compatibility” and “Generated .class files compatibility” to your desired older Java version – use a tool to make sure you didn’t use new APIs
 Animal Sniffer: http://www.mojohaus.org/animal-sniffer 
 57
  58. 58. Options for Backwards Compatibility • If you only want to use lambdas and try-with-resources – compile as Java 8, then use RetroLambda to backport your JAR file 
 https://github.com/orfjackal/retrolambda – you still have to make sure you didn’t use new APIs: AnimalSniffer again
 
 • You might be able to backport Streams too (mixed results) – http://sourceforge.net/projects/streamsupport 58
  59. 59. Is It Worth It? • Backporting? Maybe, but probably not regularly – Risky: even if it seems to work, hard to test if it really worked – make sure you have great unit tests to run against the backported code
 
 • Learning? Absolutely! – even if you can’t use Java 8 now, you will later – functional programming can be much “safer” – teaches you good coding habits – helps you understand code examples on StackOverflow ;) 59
  60. 60. Required Reading we only scratched the surface
  61. 61. On the Oracle Website • Streams – https://docs.oracle.com/javase/8/docs/api/java/util/stream/package- summary.html – http://www.oracle.com/technetwork/articles/java/ma14-java-se-8- streams-2177646.html 
 • Lambdas – https://docs.oracle.com/javase/tutorial/java/javaOO/ lambdaexpressions.html – http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html – https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27 61
  62. 62. Articles and Musings • State of the lambda (Brian Goetz) – http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html 
 • IBM DeveloperWorks articles by Brian Goetz – http://www.ibm.com/developerworks/java/library/j-java-streams-1-brian-goetz – http://www.ibm.com/developerworks/java/library/j-java-streams-2-brian-goetz – http://www.ibm.com/developerworks/java/library/j-java-streams-3-brian-goetz – http://www.ibm.com/developerworks/java/library/j-java-streams-4-brian-goetz – http://www.ibm.com/developerworks/java/library/j-java-streams-5-brian-goetz
 • Joel Spolsky on MapReduce – https://www.joelonsoftware.com/2006/08/01/can-your-programming-language- do-this 62
  63. 63. Books (!) • Java 8 in Action – Raoul-Gabriel Urma
 Manning Press • Mastering Lambdas: Java Programming in a Multicore World – Maurice Naftalin
 Oracle Press
  64. 64. Notices and disclaimers Copyright © 2017 by International Business Machines Corporation (IBM). No part of this document may be reproduced or transmitted in any form without written permission from IBM. U.S. Government Users Restricted Rights — Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM. Information in these presentations (including information relating to products that have not yet been announced by IBM) has been reviewed for accuracy as of the date of initial publication and could include unintentional technical or typographical errors. IBM shall have no responsibility to update this information. THIS DOCUMENT IS DISTRIBUTED "AS IS" WITHOUT ANY WARRANTY, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL IBM BE LIABLE FOR ANY DAMAGE ARISING FROM THE USE OF THIS INFORMATION, INCLUDING BUT NOT LIMITED TO, LOSS OF DATA, BUSINESS INTERRUPTION, LOSS OF PROFIT OR LOSS OF OPPORTUNITY. IBM products and services are warranted according to the terms and conditions of the agreements under which they are provided. IBM products are manufactured from new parts or new and used parts. In some cases, a product may not be new and may have been previously installed. Regardless, our warranty terms apply.” Any statements regarding IBM's future direction, intent or product plans are subject to change or withdrawal without notice. Performance data contained herein was generally obtained in a controlled, isolated environments. Customer examples are presented as illustrations of how those customers have used IBM products and the results they may have achieved. Actual performance, cost, savings or other results in other operating environments may vary. References in this document to IBM products, programs, or services does not imply that IBM intends to make such products, programs or services available in all countries in which IBM operates or does business. Workshops, sessions and associated materials may have been prepared by independent session speakers, and do not necessarily reflect the views of IBM. All materials and discussions are provided for informational purposes only, and are neither intended to, nor shall constitute legal or other guidance or advice to any individual participant or their specific situation. It is the customer’s responsibility to insure its own compliance with legal requirements and to obtain advice of competent legal counsel as to the identification and interpretation of any relevant laws and regulatory requirements that may affect the customer’s business and any actions the customer may need to take to comply with such laws. IBM does not provide legal advice or represent or warrant that its services or products will ensure that the customer is in compliance with any law 64
  65. 65. Notices and disclaimers continued Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products in connection with this publication and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. IBM does not warrant the quality of any third-party products, or the ability of any such third-party products to interoperate with IBM’s products. IBM EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The provision of the information contained herein is not intended to, and does not, grant any right or license under any IBM patents, copyrights, trademarks or other intellectual property right. IBM, the IBM logo, ibm.com, Aspera®, Bluemix, Blueworks Live, CICS, Clearcase, Cognos®, DOORS®, Emptoris®, Enterprise Document Management System™, FASP®, FileNet®, Global Business Services ®, Global Technology Services ®, IBM ExperienceOne™, IBM SmartCloud®, IBM Social Business®, Information on Demand, ILOG, Maximo®, MQIntegrator®, MQSeries®, Netcool®, OMEGAMON, OpenPower, PureAnalytics™, PureApplication®, pureCluster™, PureCoverage®, PureData®, PureExperience®, PureFlex®, pureQuery®, pureScale®, PureSystems®, QRadar®, Rational®, Rhapsody®, Smarter Commerce®, SoDA, SPSS, Sterling Commerce®, StoredIQ, Tealeaf®, Tivoli®, Trusteer®, Unica®, urban{code}®, Watson, WebSphere®, Worklight®, X-Force® and System z® Z/OS, are trademarks of International Business Machines Corporation, registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other companies. A current list of IBM trademarks is available on the Web at "Copyright and trademark information" at: www.ibm.com/legal/copytrade.shtml. 65
  66. 66. Thank you! Julian Robichaux @jrobichaux jrobichaux@panagenda.com

×