JAVA 8 CONTENTS New Features of java 7 Diamond Operator Using Strings in switch statement Automatic Resource Management Numeric Literals with underscore Improved exception handling File change notifications Fork and Join Features of java 8 Streams Lambda Expressions Functional Interfaces Java Date and time
Java 7 includes a few new language features , These features are quite handy for a developer.
let us have a close look at these features.
Diamond Operator If we have to declare a map of trades using Generics, we write the code as follows:
Map<String, List<Trade>> trades = new TreeMap<String, List<Trade>> (); we must declare the types on both the sides, although the right-hand side seems a bit redundant. In Java 7, its written like this:
Map<String, List<Trade>> trades = new TreeMap <> ();
You dont have to type the whole list of types for the instantiation.
Instead you use the <> symbol, which is called diamond operator.
Using strings in switch statements
Switch statements work either with primitive types or enumerated types.
Java 7 introduced another type that we can use in Switch statements: the String type.
Say we have a requirement to process a Trade based on its status. Until now we used to do this by using if-else statements. private void processTrade(Trade t) { String status = t.getStatus(); if (status.equalsIgnoreCase(NEW)) { newTrade(t); } else if (status.equalsIgnoreCase(EXECUTE)) { executeTrade(t); } else if (status.equalsIgnoreCase(PENDING)) { pendingTrade(t); } }
In JAVA 7 this is accomplished as follows:
public void processTrade(Trade t) {
String status = t.getStatus(); switch (status) { case NEW: newTrade(t); break; case EXECUTE: executeTrade(t); break; case PENDING: pendingTrade(t); break; default: break; } }
Automatic resource management
Resources such as Connections, Files, Input/OutStreams, etc. should be closed manually by the developer by writing bog-standard code. Usually we use a try-finally block to close the respective resources. public void oldTry() { try { fos = new FileOutputStream("movies.txt"); dos = new DataOutputStream(fos); dos.writeUTF("Java 7 Block Buster"); } catch (IOException e) { e.printStackTrace(); }}
Finally { try { fos.close(); dos.close(); } catch (IOException e) { // log the exception } In JAVA 7 all we have to do is declare the resources in the try as follows: try(resources_to_be_cleant){ // your code }
The above method with the old try can finally can be re-written using this new feature as shown below:
public void newTry() {
try (FileOutputStream fos = new FileOutputStream("movies.txt");
DataOutputStream dos = new DataOutputStream(fos)) {
dos.writeUTF("Java 7 Block Buster");
} catch (IOException e) {
// log the exception } } Numeric literals with underscores What is the value assigned to the variable number int number = 1000000;
Java 7 added new feature for numeric literals which can be initialized as follows int thousand = 1_000; int million = 10_00_000;
Improved exception handling public void oldMultiCatch() { try { methodThatThrowsThreeExceptions(); } catch (ExceptionOne e) { // log and deal with ExceptionOne } catch (ExceptionTwo e) { // log and deal with ExceptionTwo } catch (ExceptionThree e) { // log and deal with ExceptionThree }}
The above program code is incredibly inefficient and error prone. However in JAVA 7 the same code can be written as: public void newMultiCatch() { try { methodThatThrowsThreeExceptions(); } catch (ExceptionOne | ExceptionTwo | ExceptionThree e) { // log and deal with all Exceptions } } File change notifications This has been a long-awaited feature. The WatchService API lets you receive notification events upon changes to the subject (directory or file). The steps involved in implementing the API are: 1.Create a WatchService. This service consists of a queue to hold WatchKeys WatchService watchService = FileSystems.getDefault().newWatchService(); 2.Register the directory/file you wish to monitor with this WatchService path = Paths.get("C:\Temp\temp\");
While registering, specify the types of events you wish to receive (create, modify or delete events) path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); 3.You have to start an infinite loop to listen to events while(true) { WatchKey key = watchService.take(); // this would return you keys }
4.When an event occurs, a WatchKey is placed into the queue Consume the WatchKey and invoke queries on it for (WatchEvent<?> event : key.pollEvents()) { Kind<?> kind = event.kind(); System.out.println("Event on " + event.context().toString() + " is " + kind); } Result Event on temp is ENTRY_MODIFY Event on temp is ENTRY_DELETE Fork and Join Framework the Fork-Join breaks the task at hand into mini-tasks until the mini-task is simple enough No worker thread is idle. They implement a work-stealing algorithm in that idle workers steal the work from those workers who are busy. The core classes supporting the Fork-Join mechanism are ForkJoinPool and ForkJoinTask. ForkJoinPool is basically a specialized implementation of ExecutorService implementing the work-stealing algorithm. The problem that needs to be solved is coded in a ForkJoinTask.
Support for dynamic typed languages. Java is a statically typed language the type checking of the variables, methods and return values is performed at compile time. There are some languages for which type information is unresolved until runtime like Ruby, Python and Clojure These languages can be run on JVM using reflection but with a lot of restrictions and constraints. In Java 7, a new feature called invokedynamic was introduced A new package, java.lang.invoke, consisting of classes such as MethodHandle and others, has been created to extend the support of dynamic languages.
Static blocks: if no main() exists, static blocks will not be executed.
JAVA 8 features Streams is a new collection Streams are meant to make manipulating the data easier and faster. It uses fork/join parallelism to split up the work and speed the processing along. Obtaining a stream from a collection. Stream stream = collection.stream(); There are two "modes" for a stream: sequential and parallel. Using a sequential stream: List <Person> people = list.getStream.collect(Collectors.toList());
Using a parallel stream: List <Person> people = list.getStream.parallel().collect(Collectors.toList());
When the stream is traversed sequentially, each item in the stream is read processed, then the next item is read.
When the stream is traversed in parallel, the array is split into multiple segments, each of which is processed individually on a different thread. The results are then put back together for the output. Lambda Expressions Lambda expressions are designed to allow code to be streamlined. Avoids Verbose code. When a Lambda expression is written, it is translated into a functional interface at compile time. Here is an example of using Lambda expressions to replace an anonymous inner class with much cleaner and more readable code. Old way without Lambda: button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println(Action Detected);}} ); New way with Lambda: button.addActionListener(e -> { System.out.println(Action Detected); } ); Given a number n returns a boolean indicating if it is odd n -> n % 2 != 0; Given a character c returns a boolean indicating if it is equal to y. (char c) -> c == 'y'; Functional interfaces
An interface is a functional interface if it defines exactly one abstract method.
For instance, java.lang.Runnable is a functional interface because it only defines one abstract method:
public abstract void run();
Default methods are not abstract, so a functional interface can define as many default methods as it likes.
A new annotation, @FunctionalInterface, has been introduced. It can be placed on an interface to declare the intention of it being a functional interface. It will cause the interface to refuse to compile unless you've managed to make it a functional interface. It's sort of like @Override in this way; it declares intention and doesn't allow you to use it incorrectly.
@FunctionalInterface public interface Runnable { public abstract void run(); }
Instantiating a runnable interface. Runnable r = () -> { System.out.println("Running!"); } JAVA 8 DATE AND TIME In JAVA 6 Date and time handling in Java is a somewhat tricky part when you are new to the language. Time can be accessed via the static method System.currentTimeMillis() If you prefer to work with Objects instead you can use java.util.Date The above classes contains methods that are deprecated in the current java versions. Java 7 and below are lacking a good date and time API
IN JAVA 8 The new API specifies a number of new classes which are divided into the categories of continuous and human time. Continuous time is based on Unix time and is represented as a single incrementing number. Class Description Instant A point in time in nanoseconds from January 1st 1970 Duration An amount of time measured in nanoseconds Instant instant = Instant.now(); System.out.println(instant.toString()); //2013-05-15T05:20:08.145Z System.out.println(instant.plus(Duration.ofMillis(5000)).toString()); //2013- 05-15T05:20:13.145Z
Human time is based on fields that we use in our daily life such as day, hour, minute and second. Class Description LocalDate a date, without time of day, offset or zone LocalTime the time of day, without date, offset or zone Period a descriptive amount of time, such as "2 months and 3 days" ZonedDateTime the date and time with a time zone and offset Import javax.time.LocalDate; LocalDate date =LocalDate.now(); sop(%s-%s-%s +date.getYear(),date.getMonthValue(), Date.getDayOfMonth()); }}
LocalTime time = Localtime.now(); LocalTime newtime = time.plus(5,HOURS); OR LocalTime newtime = time.plusHours(5);
Period p = Period.of(5,HOURS); newtime=time.plus(p);