”;
JAVA 8 is a major feature release of JAVA programming language development. Its initial version was released on 18 March 2014. With the Java 8 release, Java provided supports for functional programming, new JavaScript engine, new APIs for date time manipulation, new streaming API, etc.
Following is the list of new features supported in Java 8:
Lambda Expressions
Lambda expression is one of the biggest feature introduced in Java. A lambda expression facilitates functional programming in Java. A lambda expression works on the principle of functional interface. A Functional interface is an interface with only one method to implement. A lambda expression provides an implementation of the functional interface method.
Lambda expression simplifies functional programming a lot and makes code readable without any boilerplate code. A lambda expression can infer the type of parameter used and can return a value without a return keyword. In the case of the simple one-statement method, even curly braces can be eliminated.
Example – Using Lambda Expressions
Following example showcases the use of lambda expression. A lambda expression works best with a functional interface, an interface with single abstract method. We”ve defined one interface Calculator with single method operate, which can accept two parameters and return a value. In main method, we”ve implemented the Calculator interface using anonymous function first and then using a lambda expression. The operate() method is called to print the result in both cases and results are printed.
package com.tutorialspoint; public class Tester { public static void main(String[] args) { // Interface implementation using anonymous class Calculator sum = new Calculator() { @Override public int operate(int a, int b) { return a + b; } }; int result = sum.operate(2,3); System.out.println(result); // Interface implementation using lambda expression Calculator sum1 = (a,b) -> a + b; result = sum1.operate(2,3); System.out.println(result); } interface Calculator { int operate(int a, int b); } }
Let us compile and run the above program, this will produce the following result −
5 5
Method References
Method reference is a short and concise way to call methods, static methods and even constructors without any lengthy syntax. Method references help to point to methods by their names even without specifying the arguments. Arguments are passed by the lambda expression. A method reference is described using “::” symbol.
A static method can be referred using following syntax:
<<class-name>>::methodName
An instance method can be referred using following syntax:
<<object-name>>::methodName
We can invoke constructor using following syntax:
<<class-name>>::new
Example – Using Method References
In this example, we”ve used a static method compare and an instance method compareTo to sort two arraylist of integers. We”ve used method references to represent both static and instance methods.
package com.tutorialspoint; import java.util.Arrays; import java.util.List; public class Tester { public static void main(String args[]) { List<Integer> numbers = Arrays.asList(1,2,4,9,8,7,3); System.out.println("Sorted using static method reference"); // Use static method compare numbers = numbers.stream().sorted(Integer::compare).toList(); System.out.println(numbers); numbers = Arrays.asList(1,2,4,9,8,7,3); System.out.println("Sorted using instance method reference" ); // Use instance method compareTo numbers = numbers.stream().sorted(Integer::compareTo).toList(); System.out.println(numbers); } }
Let us compile and run the above program, this will produce the following result −
Sorted using static method reference [1, 2, 3, 4, 7, 8, 9] Sorted using instance method reference [1, 2, 3, 4, 7, 8, 9]
Default Methods
Before Java 8, an interface could have only abstract methods. With Java 8, lambda expression were introduced. Now for backward compatability, default method capability was added so that old interfaces can leverage lambda expression without modifying their implementations.
For example, List or Collection interfaces do not have ”forEach” method declaration. Thus, adding such method will simply break the collection framework implementations. Java 8 introduces default method so that List/Collection interface can have a default implementation of forEach method, and the class implementing these interfaces need not implement the same.
Syntax
The following is the syntax of the default method in interface in Java −
public interface vehicle { default void message() { System.out.println("I am a vehicle!"); } }
Example – Using Default Method
In this example, we”ve created an interface with a default method. In an implementing class, this message is not implemented and is used to print a message.
package com.tutorialspoint; interface vehicle { // default method must have an implementation default void message() { System.out.println("I am a vehicle!"); } } // implementing class need not to implement the default method // of an interface. public class Tester implements vehicle { public static void main(String args[]) { Tester tester = new Tester(); // implementing class can access the default method as its own method tester.message(); } }
Let us compile and run the above program, this will produce the following result −
I am a vehicle!
Stream API
Stream API is a new abstract layer introduced in Java 8 to process data in a declarative way. A stream represents a sequence of elements. A stream provides a set of elements of specific type in a sequential manner. A stream gets/computes elements on demand. It never stores the elements.
Stream supports aggregate operations like filter, map, limit, reduce, find, match, and so on and can do the iterations internally over the source elements provided, in contrast to Collections where explicit iteration is required.
Syntax
Following is the generic syntax to use a stream
<<collection-instance>>.stream().<<non-terminal-operation()>>.<<non-terminal-operation()>>.<<terminal-operation()>>
Example – Using Stream
In this example, we”ve created a list of strings where few entries are empty. Now using stream API, we”re filtering the empty strings and counting them.
package com.tutorialspoint; import java.util.Arrays; import java.util.List; public class Tester { public static void main(String args[]) { List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // get stream from list using stream() method // then apply filter // lastly count the result of filter long count = strings.stream().filter(string->string.isEmpty()).count(); System.out.println("Empty Strings: " + count); } }
Let us compile and run the above program, this will produce the following result −
Empty Strings: 2
Optional Class
Optional class feature was introduced in java 8 to handle Null Pointer Exception scenarios programmatically, to make programs more concise, less error prone. A Null Pointer Exception occurs whenever a null object reference is used to get value from it or to invoke its method. As program size increases, it is very tedious to handle all cases where Null Pointer Exception can happens.
Optional Class instance provides a wrapper over the object with many utility methods like to get the alternate value if underlying value is null, to check if object reference is null and so.
Example – Using Optional Class
In this example, we”ve created two Optional class instance using oofNullable() method which allows to pass underlying object as null and then retrieved the value using orElse() method, which returns a default value if underlying object is null.
package com.tutorialspoint; import java.util.Optional; public class Tester { public static void main(String args[]) { // case 1: Optional is having null as underlying value Optional<Integer> valueOptional = Optional.ofNullable(null); // case 2: Optional is having not null as underlying value Optional<Integer> valueOptional1 = Optional.ofNullable(Integer.valueOf(10)); // orElse will return -1 being default value Integer value = valueOptional.orElse(Integer.valueOf(-1)); System.out.println(value); // orElse will return the underlying value Integer value1 = valueOptional1.orElse(Integer.valueOf(-1)); System.out.println(value1); } }
Let us compile and run the above program, this will produce the following result −
-1 10
New Date Time API
Java 8 introduced a new Date Time API which is thread safe, zone ready and multiple direct methods to handle date operations. Earlier date-time API was not thread safe and in concurrency issues could pop up while working with dates. New date time APIs are using immutable constructs and no setter method thus making API more secure. The new API is designed considering zone, domain specific requirements.
Java 8 introduces a new date-time API under the package java.time. Following are some of the important classes introduced in java.time package.
-
Local − Simplified date-time API with no complexity of timezone handling.
-
Zoned − Specialized date-time API to deal with various timezones.
Example – Using Date Time APIs
In this example, we”ve created two Optional class instance using oofNullable() method which allows to pass underlying object as null and then retrieved the value using orElse() method, which returns a default value if underlying object is null.
package com.tutorialspoint; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; import java.time.ZonedDateTime; public class Tester { public static void main(String args[]) { // Get the current date and time LocalDateTime currentTime = LocalDateTime.now(); System.out.println("Current DateTime: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); Month month = currentTime.getMonth(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("Month: " + month +", day: " + day +", seconds: " + seconds); ZonedDateTime date2 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]"); System.out.println("date2: " + date2); } }
Let us compile and run the above program, this will produce the following result −
Current DateTime: 2024-03-07T10:29:15.650806 date1: 2024-03-07 Month: MARCH, day: 7, seconds: 15 date2: 2007-12-03T09:45:30+05:00[Asia/Karachi]
Nashorn JavaScript Engine
Nashorn, a very powerful and efficient Javascript engine, is introduced as a replacement of existing javascript engine, Rhino. Nashorn engine is touted to be 2 to 10 times faster as it can directly compile the JavaScript Code to bytecode. Nashorn engine allows to run execute JavaScript code in Java file and we can even execute java code within a JavaScript code snippet. With Nashorn engine, a command line tool jjs was introduced to run the javascript in command line tools.
Execute JavaScript Directly in Command Prompt
Open the console and type jjs and press enter button. jjs tool will open an interactive session. Once jjs session is open, we can execute a javascript code. Once done, type quit() and press enter button to exit the jjs interactive session and to return back to the command prompt.
Example
C:JAVA>jjs jjs> print("Hello, World!") Hello, World! jjs> quit() >> C:JAVA>
Example – Using Javascript code within Java Code
Java has a ScriptEngineManager class since Java 6, which is used in this example to load the javascript engine as ScriptEngine instance. Once engine is loaded in the java code, we can call eval() method to evaluate a JavaScript code in Java. We can even use Java variable(s) in javascript code snippet.
package com.tutorialspoint; import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import javax.script.ScriptException; public class Tester { public static void main(String args[]) { // create the script engine manager ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); // load the Nashorn javascript engine ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn"); String message = "This is a message"; String expression = "10 + 2"; Integer result = null; try { // call the javascript function, pass a java variable nashorn.eval("print(''" + message + "'')"); // call the javascript function and get the result back in java result = (Integer) nashorn.eval(expression); } catch(ScriptException e) { System.out.println("Error executing script: "+ e.getMessage()); } System.out.println(result.toString()); } }
Let us compile and run the above program, this will produce the following result −
This is a message 12
Nashorn engine was deprecated in java 11 and removed in java 15 and is replaced by GraalVM javascript engine.
”;