Certification • Recap of some Java 7 Features • Java 8 Overview – Lambda Expressions • Method References • Default Methods – Optionals – Stream API – Date and Time API
Must pass OCA first • 90 multiple choice questions, 150 minutes, passing score 65% • Example topics like class design, generics, collections, I/O, NIO.2, JDBC, Threads, Localization etc. • Upgrade exam available if you have previous Java certificate
overall – 1) Small language changes (Project Coin) • JSR 334: Small language changes (Project Coin) – 2) Updates to File API • JSR 203: New file I/O library – 3) Updates to virtual machine, invokedynamic – 4) Lot of smaller updates • Unicode 6.0, JDBC autocloseable, Java 2D and Swing updates, xml stack update...
7 1. Strings in switch 2. Binary integral literals and underscores in numeric literals 3. Improved Type Inference for Generic Instance Creation 4. Multi-‐catch 5. try-‐with-‐resources statement
{ String language = "Java"; switch(language) { case "Java": System.out.println("Hello from Java!"); break; case "PHP": System.out.println("Hello from PHP!"); break; default: System.out.println("Not Java or PHP"); } } }
class BinaryLiterals { public static void main(String [] args) { long billion = 1_000_000_000; int one = 0b0000_0001; System.out.println(billion); System.out.println(one); } }
method upon exiting the try block (like finally) • The resource object must implement AutoCloseable interface • The interface has only one method: close • If closing causes exception, it’s suppressed (ignore). Possible to get it using getSuppressed() method
updated • Called NIO.2 revision • New classes (java.nio): – Path – Locate a file in a file system • Paths – Convert a URI to Path object – Files – Operate on files, directories and other types of files – FileVisitor – Traversing files in a tree – WatchService – File change modification API
Example: delete every .class file in a tree • Implement a class that implements FileVisitor interface – preVisitDirectory – postVisitDirectory – visitFile – visitFileFailed • Or extend SimpleFileVisitorthat has default behaviour for each of these methods!
notifies if someone else has made changes to your document – (“The following files were changes by another program”) • Watch Service API enables you to register a directory with the watch service • When registering tell are you interested in file creation, file deletion or file modification!
{ Runnable r1 = new Runnable() { public void run() { System.out.println("Hello!"); } }; new Thread(r1).start(); // Same than class Anonymous implements Runnable { public void run() { System.out.println("Hello!"); } } Runnable r2 = new Anonymous(); new Thread(r2).start(); // Does the same but is NOT the same Runnable r3 = () -‐> System.out.println("Hello!"); new Thread(r3).start(); } } Lambda is not an inner class!
method • To declare an functional interface, use annotation @FunctionalInterface – No ambiguity of which method should the lambda define in the interface! • You will get compiler error if you have the annotation and several methods in interface • If interface has only one method, it's functional.
[] args) { String [] data = {"a", "bb", "b", "kkk", "jjjj"}; Comparator<String> comparator = (a, b) -‐> { return a.length() -‐ b.length(); }; Arrays.sort(data, comparator); System.out.println(Arrays.toString(data)); } } If target type is Comparator<String>, then arguments must be String! No need to declare these!
[] args) { String [] data = {"a", "bb", "b", "kkk", "jjjj"}; Arrays.sort(data, (a, b) -‐> { return a.length() -‐ b.length(); }); System.out.println(Arrays.toString(data)); } } If data is String[] then it must be passed Comparator<String>
[] args) { String [] data = {"a", "bb", "b", "kkk", "jjjj"}; Arrays.sort(data, (a, b) -‐> a.length() -‐ b.length()); System.out.println(Arrays.toString(data)); } } If you use single expression, Java runtime evaluates the expression and returns a value!
actionEvent; public Main(String title) { super(title); JButton click = new JButton("Click"); add(click); click.addActionListener((actionEvent) -‐> { this.actionEvent = actionEvent; }); setSize(300, 300); setVisible(true); } public static void main(String[] args) { new Main("Title"); } } this does not reference to the lambda! This works!
1; public void method() { int y = 2; final int z = 3; class Inner { public void method() { System.out.println(x); System.out.println(y); System.out.println(z); } } new Inner().method(); } } class Main { public static void main(String[] args) { new Outer().method(); } }
int x = 1; public void method() { int y = 2; final int z = 3; class Inner { public void method() { System.out.println(x); System.out.println(y); System.out.println(z); } } new Inner().method(); } } class Main { public static void main(String[] args) { new Outer().method(); } } Java 7: only final variables allowed. Java 8: final and effectively final variables allowed!
public void method() { int y = 2; // Effectively final, java 8: YES, java 7: NO final int z = 3; // Final, java 8: YES, java 7: YES int v = 1; v = 2; // Variable, java 8: NO, java 7: NO class Inner { public void method() { System.out.println(x); System.out.println(y); System.out.println(z); // System.out.println(v); } } new Inner().method(); } } class Main { public static void main(String[] args) { new Outer().method(); } }
main(String [] args) { Person [] array = {new Person("jack", "smith"), new Person("tina", "bauer")}; // Use anonymous inner class to sort but use a method already // defined. Arrays.sort(array, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return Person.compareByLastName(o1, o2); } } ); // Use lambda Arrays.sort(array, (Person o1, Person o2) -‐> { return Person.compareByLastName(o1, o2); } ); // Since array type is String, o1 and o2 must be String // and you don't have to declare them. Arrays.sort(array, (o1, o2) -‐> { return Person.compareByLastName(o1, o2); } ); // By default lambda will return the value of a single expression Arrays.sort(array, (o1, o2) -‐> Person.compareByLastName(o1, o2) ); // Since we are calling only one method in lambda, we are // using a method reference! Arrays.sort(array, Person::compareByLastName ); System.out.println(Arrays.toString(array)); } } Static method reference: Person.compareByLastName(o1, o2)
int compareByLastName(Person a, Person b) { System.out.println("a"); return a.lastName.compareTo(b.lastName); } public int compareByFirstName(Person a, Person b) { return a.firstName.compareTo(b.firstName); } public int compareByFirstName(Person b) { return this.firstName.compareTo(b.firstName); } } class Main { public static void main(String [] args) { Person [] array = {new Person("jack", "smith"), new Person("tina", "bauer")}; // Static method reference // -‐> Person.compareByLastName(o1, o2) Arrays.sort(array, Person::compareByLastName ); // Object method reference // -‐> new Person().compareByFirstName(o1, o2) Arrays.sort(array, new Person()::compareByFirstName ); // Instance method of an arbitrary object of particular type // -‐> o1.compareByFirstName(o2) Arrays.sort(array, Person::compareByFirstName ); System.out.println(Arrays.toString(array)); } } This can mean both o1.compareByFirstname(o2) and Person.compareByFirstname(o1, o2)! If you have both methods in class, you will have a compiler error!
Java 7: if you add another method to interface, every class implementing that interface must implemented again • Helps to create utility classes where implementation is part of the interface • Can provide default implementation of methods for classes. Class may override the implementation
public void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface Movable { public void start(); public void stop(); public void fly(); } class MyApp { public static void main(String [] args) { new Robot().start(); } } Now every class that has implemented the Movable must be changed!
void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface Movable { public void start(); public void stop(); default public void fly() { System.out.println("I'm flying!"); } } class MyApp { public static void main(String [] args) { new Robot().fly(); } } No changes to Robot, suddenly it holds a new method fly. Robot can also override this.
about doing operations on elements! • Stream API provides a powerful way of do different kind of operations on data – filtering – sorting – ... • Streams can be created from collections – stream() and parallelStream() • Streams are all about computations, collections are about data
source that supports aggregate operations • Sequence of elements from a source – Source can be collection, array, I/O – Stream is an interface to the elements • Aggregate Operations – filter, map, reduce, find, match, sorted ...
returns a stream itself. Allows operations to be chained to form a larger pipeline • Internal iteration happens behind the scenes, so developer does not have iterate the collections
and just a bunch of objects – Stream.of("a1", "a2", "a3").filter(...).forEach(...) • Also for primitive types – IntStream.range(1, 4).filter(...).forEach(...)
stream to a new result – List, Set, Map • Collect accepts Collector – Various built-‐in Collectors available via Collectors – class • Collectors.toSet(), Collectors.toList(), Collectors.toMap()
String) -‐> String? { if(company == "Nokia") { return "NOK"; } else if (company == "Apple") { return "AAPL"; } else { return nil; } } } var code : String? = StockExchange.findStockCode( Process.arguments[1] ); // Compile error! // Its a hint for the developer that you must check nil values! println(code.lowercaseString); String? is an optional String. Can contain nil or String
pet: Pet? } class Pet { var name: String var favoriteToy: Toy? init(name: String) { self.name = name } } class Toy { var name: String? init(name: String) { self.name = name } } 92 // Create person var jack = Person() // Create pet var spot = Pet(name: "Spot") // Create toy var ball = Toy(name: "Ball") // Jack will have a pet named Spot which favorite // toy is ball spot.favoriteToy = ball jack.pet = spot // Printing the name.... Aaargh! if var pet = jack.pet { if var toy = pet.favoriteToy { if var name = toy.name { println(name) } } }
will crash if some of these is // nil var name1 : String = jack.pet!.favoriteToy!.name! println(name1) // "Ball" // Will return always on optional string // result is nil, if pet, favoriteToy or name is nil var name2 : String? = jack.pet?.favoriteToy?.name println(name2) // Optional("Ball") // If pet, favoriteToy or name is nil, don't execute // the code. If these are not nil, fetch the name // AND unwrap it if var name3 = jack.pet?.favoriteToy?.name { println(name3) } 93
these return NULL – String version = computer.getSoundcard().getUSB().getVersion(); • A lot nested checks (if not null) is required here. • Java 8 Introduces a new class called java.util.Optional<T> to handle this • Single-‐value container that either contains a value or not (null)
// motor may hold value or null this.motor = Optional.ofNullable(motor); } public Car() { this.motor = Optional.empty(); } public Optional<Motor> getMotor() { return motor; } public void setMotor(Motor motor) { this.motor = Optional.of(motor); } } class Motor { private int horsePower; public Motor(int horsePower) { this.horsePower = horsePower; } public int getHorsePower() { return horsePower; } public void setHorsePower(int horsePower) { this.horsePower = horsePower; } } class Main { public static void main(String[] args) { Car datsun = new Car( new Motor(40) ); datsun.getMotor().ifPresent(motor -‐> { System.out.println(motor.getHorsePower()); }); Car skoda = new Car( null ); skoda.getMotor().ifPresent(motor -‐> { System.out.println(motor.getHorsePower()); }); Car peugeot = new Car(); peugeot.getMotor().ifPresent(motor -‐> { System.out.println(motor.getHorsePower()); }); } } Programmer is now forced to think about what happens if the result is null!
Optional.empty(); // an 'Optional' where you know that it will not contain null; // (if the parameter for 'of' is null, a // 'NullPointerException' is thrown) Optional<String> full = Optional.of("Some String"); // an 'Optional' where you don't know whether // it will contain null or not Optional<String> halfFull = Optional.ofNullable(someOtherString);
{ Toy ball = new Toy("ball"); Pet spot = new Pet(ball, "Spot"); Human jack = new Human(spot); // If getPet has a value, unwrap the optional from // getPet and invoke it's getName() method // // if getPet has no value, then return empty Optional Optional<String> name = jack.getPet().map(Pet::getName); // print the name if jack.getPet() was not null! name.ifPresent(System.out::println); } }
{ Toy ball = new Toy("ball"); Pet spot = new Pet(ball, "Spot"); Human jack = new Human(spot); // Did we manage to retrieve the name? Optional<String> maybeName = jack.getPet().map(Pet::getName); // Is the name "Spot"? Optional<String> maybeSpot = maybeName.filter(n -‐> { return n.equals("Spot"); }); // If "Spot" was present, print it out maybeSpot.ifPresent(System.out::println); } }
{ Toy ball = new Toy("ball"); Pet spot = new Pet(ball, "Spot"); Human jack = new Human(spot); // If jack has a pet and it's name is Spot, print the name to console jack.getPet().map(p -‐> p.getName()) .filter(name -‐> name.equals("Spot")) .ifPresent(name -‐> System.out.println(name) ); } }
Toy ball = new Toy("ball"); Pet spot = new Pet(ball, "Spot"); Human jack = new Human(spot); Optional<Pet> maybePet = jack.getPet(); // Notice that getName returns String, but name here is // Optional! It's optional because maybePet may contain null. Optional<String> name = maybePet.map(pet -‐> pet.getName()); // Now the pet.getToy return Optional<Toy>, so the end result // is Optional<Optional<Toy>>!! Optional<Optional<Toy>> maybeMaybeToy = maybePet.map(pet -‐> pet.getToy()); // Use flatMap instead of flat! Optional<Toy> maybeToy = maybePet.flatMap(pet -‐> pet.getToy()); // MAGIC! :) String toyName = jack.getPet().flatMap(Pet::getToy).map(Toy::getName).orElse("Default"); System.out.println(toyName); } }
another date and time library? – Existing classes on Thread-‐safe and exhibit poor API Design – Has lead to third-‐party options about Date and Time libraries • New API – Objects immutable (no setX – methods) and therefore Thread-‐safe – Clear and Fluent API – Extensible (you can build your own calendar system)
Time zones, Duration and Clocks • java.time.chrono – Alternative calendar systems (other than ISO-‐8601) like Buddhist • java.time.format – Formatting times in different formats • java.time.temporal – Formatting and parsing dates and times • java.time.zone – Classes for time zones
main(String[] args) { // Good for time stamp to represent machine time // Counts time beginning from 1970-‐01-‐01T00:00:00Z Instant now = Instant.now(); // 2015-‐08-‐19T07:25:33.361Z System.out.println(now); Instant oneHourLater = now.plusSeconds(60 * 60); // 2015-‐08-‐19T08:23:44.110Z System.out.println(oneHourLater); } }