1. Introduction

Without a doubt, Java 8 is the most important release of Java since Java 5 (released in 2004). This release includes more than a dozen new features in languages, compilers, libraries, tools, and JVMS. In this article, we’ll learn about these new features and use practical examples to show where they are appropriate.

This tutorial covers several types of questions that Java developers often face:

  • language
  • The compiler
  • library
  • tool
  • Runtime (JVM)

2. New features of the Java language

Java 8 is a major release of Java, and while these new features are eagerly awaited by Java developers, they also require a lot of effort to learn. In this section, we’ll cover most of the new features of Java 8.

2.1 Lambda expressions and functional interfaces

Lambda expressions (also known as closures) are the biggest and most anticipated language change in Java 8. It allows us to pass functions as arguments to a method, or to treat the code itself as data: functional developers are familiar with these concepts. Many languages on the JVM platform (Groovy, Scala, etc.) have supported Lambda expressions since their inception, but Java developers have had no choice but to use anonymous inner classes instead of Lambda expressions.

The design of Lambda took a lot of time and community effort to find a compromise that could achieve a concise and compact language structure. The simplest Lambda expressions can consist of comma-separated argument lists, -> symbols, and statement blocks, such as:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
Copy the code

The type of the argument e in this code is inferred by the compiler. You can also specify the type of the argument explicitly, for example:

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
Copy the code

If a Lambda expression requires a more complex block, it can be enclosed in curly braces, similar to the body of a function in Java, for example:

`Arrays.asList( "a", "b", "d" ).forEach( e -> {`
Copy the code
`System.out.print( e ); `Copy the code
`System.out.print( e ); `Copy the code
`} );`
Copy the code

Lambda expressions can refer to class members and local variables (which are implicitly converted to final). For example, the following two code blocks have exactly the same effect:

String separator = ",";
Copy the code
Arrays.asList( "a", "b", "d" ).forEach(
Copy the code
( String e ) -> System.out.print( e + separator ) );
Copy the code

and

final String separator = ",";
Copy the code
Arrays.asList( "a", "b", "d" ).forEach(
Copy the code
( String e ) -> System.out.print( e + separator ) );
Copy the code

Lambda expressions have return values, and the type of the return value is inferred by the compiler. If the block in a Lambda expression is only one line, you can skip the return statement. The following two code snippets have the same effect:

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
Copy the code

and

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
Copy the code
int result = e1.compareTo( e2 );
Copy the code
return result;
Copy the code
});Copy the code

Lambda designers considered many ways to make existing functions compatible with Lambda expressions, resulting in the concept of functional interfaces. A functional interface is an interface that has only one function, and such an interface can be implicitly converted to a Lambda expression. Java. Lang. Runnable and Java. Util. Concurrent. Callable is the best example of functional interface. In practice, functional interfaces are very fragile: as soon as a developer adds a function to the interface, the interface ceases to be functional and thus fails compilation. To overcome this code-level vulnerability and explicitly state that an interface is functional, Java 8 provides a special annotation @functionalinterface (all relevant interfaces in the Java library already carry this annotation). Here’s a simple definition of a FunctionalInterface:

`@FunctionalInterface`
Copy the code
`public interface Functional {`
Copy the code
`void method(); `Copy the code
`} `Copy the code

It is important to note, however, that the default and static methods do not break the definition of a functional interface, so the following code is legal.

`@FunctionalInterface`
Copy the code
`public interface FunctionalDefaultMethods {`
Copy the code
`void method(); `Copy the code
`default void defaultMethod() {`
Copy the code
`} `Copy the code
`} `Copy the code

Lambda expressions, the biggest selling point of Java 8, have the potential to attract more developers to the JVM platform and to use the concepts of functional programming in pure Java programming. If you need more details on Lambda expressions, refer to the official documentation.

2.2 Default methods and static methods of interfaces

Java 8 expands the meaning of interfaces with two new concepts: default methods and static methods. The default approach makes interfaces look a bit like traits, but for a different purpose. The default method allows developers to add a new method to an existing interface without breaking binary compatibility, that is, it does not force classes that implement the interface to also implement the new method.

The difference between the default method and the abstract method is that the abstract method needs to be implemented, while the default method does not. The default methods provided by the interface are inherited or overridden by the implementation class of the interface, as shown in the following example:

`private interface Defaulable {`
Copy the code
`// Interfaces now allow default methods, the implementer may or`
Copy the code
`// may not implement (override) them.`
Copy the code
`default String notRequired() {`
Copy the code
`return "Default implementation"; `Copy the code
`} `Copy the code
`} `Copy the code
`private static class DefaultableImpl implements Defaulable {`
Copy the code
`} `Copy the code
`private static class OverridableImpl implements Defaulable {`
Copy the code
`@Override`
Copy the code
`public String notRequired() {`
Copy the code
`return "Overridden implementation"; `Copy the code
`} `Copy the code
`} `Copy the code

The Defaulable interface defines a default method notRequired() using the keyword default. The DefaultableImpl class implements this interface and inherits its default methods by default. The OverridableImpl class also implements this interface, but overrides its default methods and provides a different implementation.

Another interesting feature that Java 8 brings is the ability to define static methods in interfaces, as shown in the following code:

private interface DefaulableFactory {
Copy the code
// Interfaces now allow static methods
Copy the code
static Defaulable create( Supplier< Defaulable > supplier ) {
Copy the code
return supplier.get();
Copy the code
}
Copy the code
}
Copy the code

The following code snippet integrates the default method and static method usage scenarios:

`public static void main( String[] args ) {`
Copy the code
`Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new ); `Copy the code
`System.out.println( defaulable.notRequired() ); `Copy the code
`defaulable = DefaulableFactory.create( OverridableImpl::new ); `Copy the code
`System.out.println( defaulable.notRequired() ); `Copy the code
`} `Copy the code

The output of this code is as follows:

`Default implementation`
Copy the code
`Overridden implementation`
Copy the code

Because the implementation of default methods on the JVM provides support at the bytecode level, this is very efficient. The default approach allows the interface to be improved without breaking the existing inheritance architecture. This feature is used in official libraries by adding new methods to the java.util.collection interface, such as stream(), parallelStream(), forEach(), removeIf(), and so on.

Despite the benefits of default methods, they should be used with caution in practice: in complex inheritance systems, default methods can cause ambiguity and compilation errors. If you want more details, you can refer to the official documentation.

2.3 Method Reference

Method references allow developers to refer directly to existing methods, Java class constructors, or instance objects. Method references are used in conjunction with Lambda expressions to make the constructors of Java classes look compact and concise, without a lot of complex template code.

In Simon’s case, the Car class is an example of different method references to help readers distinguish between the four types of method references.

public static class Car {
Copy the code
public static Car create( final Supplier< Car > supplier ) {
Copy the code
return supplier.get();
Copy the code
}
Copy the code
public static void collide( final Car car ) {
Copy the code
System.out.println( "Collided " + car.toString() );
Copy the code
}
Copy the code
public void follow( final Car another ) {
Copy the code
System.out.println( "Following the " + another.toString() );
Copy the code
}
Copy the code
public void repair() {
Copy the code
System.out.println( "Repaired " + this.toString() );
Copy the code
}
Copy the code
}
Copy the code

The first type of method reference is a constructor reference with the syntax Class::new or, more generally, Class::new. Note: This constructor takes no arguments.

`final Car car = Car.create( Car::new ); `Copy the code
`final List< Car > cars = Arrays.asList( car ); `Copy the code

The second type of method reference is a static method reference with the syntax Class::static_method. Note: This method takes an argument of type Car.

cars.forEach( Car::collide );
Copy the code

The third method refers to a reference to a member method of a Class. The syntax is Class::method. Note that this method has no input arguments:

cars.forEach( Car::repair );
Copy the code

The fourth method refers to a reference to a member method of an instance object with the syntax instance::method. Note: This method takes a Car parameter:

`final Car police = Car.create( Car::new ); `Copy the code
`cars.forEach( police::follow ); `Copy the code

Running the above example, you can see the following output on the console (Car instances may vary) :

Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Copy the code
Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Copy the code
Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d
Copy the code

For more details, please refer to the official documentation

2.4 Repeated notes

Since the introduction of annotations in Java 5, this feature has become very popular and is widely used in various frameworks and projects. However, there is one big limitation to annotations: you can’t use the same annotation more than once in the same place. Java 8 breaks this limitation by introducing the concept of repeated annotations, allowing the same annotation to be used multiple times in the same place.

Using the @REPEATable annotation to define Repeatable annotations in Java 8 is actually not a language improvement, but a trick made by the compiler. The underlying technology is still the same. You can use the following code to illustrate:

`package com.javacodegeeks.java8.repeatable.annotations; `Copy the code
`import java.lang.annotation.ElementType; `Copy the code
`import java.lang.annotation.Repeatable; `Copy the code
`import java.lang.annotation.Retention; `Copy the code
`import java.lang.annotation.RetentionPolicy; `Copy the code
`import java.lang.annotation.Target; `Copy the code
`public class RepeatingAnnotations {`
Copy the code
`@Target( ElementType.TYPE )`
Copy the code
`@Retention( RetentionPolicy.RUNTIME )`
Copy the code
`public @interface Filters {`
Copy the code
`Filter[] value(); `Copy the code
`} `Copy the code
`@Target( ElementType.TYPE )`
Copy the code
`@Retention( RetentionPolicy.RUNTIME )`
Copy the code
`@Repeatable( Filters.class )`
Copy the code
`public @interface Filter {`
Copy the code
`String value(); `Copy the code
`}; `Copy the code
`@Filter( "filter1" )`
Copy the code
`@Filter( "filter2" )`
Copy the code
`public interface Filterable {`
Copy the code
`} `Copy the code
`public static void main(String[] args) {`
Copy the code
`for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {`
Copy the code
`System.out.println( filter.value() ); `Copy the code
`} `Copy the code
`} `Copy the code
`} `Copy the code

As we can see, the Filter class here is modified with the @REPEATable (Filters.class) annotation, and Filters are the containers that hold the Filter annotation. The compiler tries to hide these details from the developer. Thus, the Filterable interface can be annotated with two Filter annotations (nothing about Filters is said here).

In addition, the reflection API provides a new method: GetAnnotationsByType (), can return to a certain type of repeated notes, such as Filterable. Class. GetAnnoation (Filters. Class) will return the two Filter as an example, the contents of the output to the console as shown below:

filter1
Copy the code
filter2
Copy the code

If you want to learn more, you can refer to the official documentation.

2.5 Better type inference

The Java 8 compiler has made significant improvements in type inference, allowing the compiler to deduce the data type of a parameter in many scenarios, resulting in cleaner code. Example code is as follows:

`package com.javacodegeeks.java8.type.inference; `Copy the code
`public class Value< T > {`
Copy the code
`public static< T > T defaultValue() {`
Copy the code
`return null; `Copy the code
`} `Copy the code
`public T getOrDefault( T value, T defaultValue ) {`
Copy the code
`return ( value ! = null ) ? value : defaultValue; `Copy the code
`} `Copy the code
`} `Copy the code

The following code applies the Value type:

package com.javacodegeeks.java8.type.inference;
Copy the code
public class TypeInference {
Copy the code
public static void main(String\[\] args) {
Copy the code
final Value< String > value = new Value<>();
Copy the code
value.getOrDefault( "22", Value.defaultValue() );
Copy the code
}
Copy the code
}
Copy the code

The type of the value.defaultValue () argument is derived by the compiler and does not need to be specified explicitly. In Java 7, this code will compile errors unless Value.

defaultValue() is used.

2.6 Expand the application scenarios of annotations

Java 8 broadens the scope of annotations. Annotations can now be used on almost any element: local variables, interface types, superclasses and interface implementation classes, and even on the exception definition of functions. Here are some examples:

`package com.javacodegeeks.java8.annotations; `Copy the code
`import java.lang.annotation.ElementType; `Copy the code
`import java.lang.annotation.Retention; `Copy the code
`import java.lang.annotation.RetentionPolicy; `Copy the code
`import java.lang.annotation.Target; `Copy the code
`import java.util.ArrayList; `Copy the code
`import java.util.Collection; `Copy the code
`public class Annotations {`
Copy the code
`@Retention( RetentionPolicy.RUNTIME )`
Copy the code
`@Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )`
Copy the code
`public @interface NonEmpty {`
Copy the code
`} `Copy the code
`public static class Holder< @NonEmpty T > extends @NonEmpty Object {`
Copy the code
`public void method() throws @NonEmpty Exception {`
Copy the code
`} `Copy the code
`} `Copy the code
`@SuppressWarnings( "unused" )`
Copy the code
`public static void main(String[] args) {`
Copy the code
`final Holder< String > holder = new @NonEmpty Holder< String >(); `Copy the code
`@NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>(); `Copy the code
`} `Copy the code
`} `Copy the code

Elementtype. TYPE_USER and elementtype. TYPE_PARAMETER are two new annotations in Java 8 that describe how annotations are used. The Java language has also been changed to recognize these new annotations.

3. New features for the Java compiler

3.1 Parameter Name

To get the parameter names of methods in Java programs at run time, older Java programmers had to use different methods, such as Paranamer Liberary. Java 8 has finally normalized this feature, providing support both at the language level (using reflection apis and parameter.getName () methods) and at the bytecode level (using the new Javac compiler and the -parameters Parameter).

`package com.javacodegeeks.java8.parameter.names; `Copy the code
`import java.lang.reflect.Method; `Copy the code
`import java.lang.reflect.Parameter; `Copy the code
`public class ParameterNames {`
Copy the code
`public static void main(String[] args) throws Exception {`
Copy the code
`Method method = ParameterNames.class.getMethod( "main", String[].class ); `Copy the code
`for( final Parameter parameter: method.getParameters() ) {`
Copy the code
`System.out.println( "Parameter: " + parameter.getName() ); `Copy the code
`} `Copy the code
`} `Copy the code
`} `Copy the code

This feature is turned off by default in Java 8, so if you compile the above code without the -parameters parameter and run it, you will get the following output:

Parameter: arg0
Copy the code

If -parameters is used, the following result is printed (correct) :

Parameter: args
Copy the code

If you use Maven for project management, you can configure the -parameters parameter in the maven-compiler-plugin compiler configuration item:

<plugin>
Copy the code
<groupId>org.apache.maven.plugins</groupId>
Copy the code
<artifactId>maven-compiler-plugin</artifactId>
Copy the code
< version > 3.1 < / version >Copy the code
<configuration>
Copy the code
<compilerArgument>-parameters</compilerArgument>
Copy the code
The < source > 1.8 < / source >Copy the code
The < target > 1.8 < / target >Copy the code
</configuration>
Copy the code
</plugin>
Copy the code

4. New features in the Official Java library

Java 8 adds many new utility classes (date/time classes) and extends existing ones to support modern concurrent programming, functional programming, and more.

4.1 Optional

The most common bug in Java applications is null-value exceptions. Prior to Java 8, Google Guava introduced the Optionals class to resolve NullPointerExceptions, preventing source code from being contaminated by various NULL checks and allowing developers to write cleaner code. Java 8 also added Optional to the official library.

Optional is just an easy way to store values of type T or NULL.

Let’s look at a few examples of using Optional: values that may be null or of some type:

Optional< String > fullName = Optional.ofNullable( null );
Copy the code
System.out.println( "Full Name is set? " + fullName.isPresent() );
Copy the code
System.out.println( "Full Name: " + fullName.orElseGet( () -> "\[none\]" ) );
Copy the code
System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ));Copy the code

The isPresent() method returns true if the Optional instance holds a non-null value, false otherwise; The orElseGet() method, where Optional instances hold null, can accept a default generated by a lambda expression; The map() method converts the value of an existing Opetional instance to a new value; The orElse() method is similar to the orElseGet() method, but returns the default value passed in when null is held.

The output of the above code is as follows:

`Full Name is set? false`
Copy the code
`Full Name: [none]`
Copy the code
`Hey Stranger! `Copy the code

Here’s another simple example:

Optional< String > firstName = Optional.of( "Tom" );
Copy the code
System.out.println( "First Name is set? " + firstName.isPresent() );
Copy the code
System.out.println( "First Name: " + firstName.orElseGet( () -> "\[none\]" ) );
Copy the code
System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ));Copy the code
System.out.println();
Copy the code

The output of this example is:

`First Name is set? true`
Copy the code
`First Name: Tom`
Copy the code
`Hey Tom! `Copy the code

4.2 Streams

This is one of the biggest improvements to the Java library so far, allowing developers to write more efficient, concise, and compact code.

The Steam API greatly simplifies collection operations (we’ll see more than that later), starting with a class called Task:

`public class Streams {`
Copy the code
`private enum Status {`
Copy the code
`OPEN, CLOSED`
Copy the code
`}; `Copy the code
`private static final class Task {`
Copy the code
`private final Status status; `Copy the code
`private final Integer points; `Copy the code
`Task( final Status status, final Integer points ) {`
Copy the code
`this.status = status; `Copy the code
`this.points = points; `Copy the code
`} `Copy the code
`public Integer getPoints() {`
Copy the code
`return points; `Copy the code
`} `Copy the code
`public Status getStatus() {`
Copy the code
`return status; `Copy the code
`} `Copy the code
`@Override`
Copy the code
`public String toString() {`
Copy the code
`return String.format( "[%s, %d]", status, points ); `Copy the code
`} `Copy the code
`} `Copy the code
`} `Copy the code

The Task class has a concept of score (or pseudo-complexity) and two states: OPEN or CLOSED. Now suppose you have a collection of tasks:

`final Collection< Task > tasks = Arrays.asList(`
Copy the code
`new Task( Status.OPEN, 5 ),`
Copy the code
`new Task( Status.OPEN, 13 ),`
Copy the code
`new Task( Status.CLOSED, 8 )`
Copy the code
`); `Copy the code

Let’s start with a question: how many OPEN points are there in this task set? Prior to Java 8, to solve this problem, you used a foreach loop to iterate over a collection of tasks; But in Java 8 you can take advantage of Steams, which includes a list of elements and supports sequential and parallel processing.

`// Calculate total points of all active tasks using sum()`
Copy the code
`final long totalPointsOfOpenTasks = tasks`
Copy the code
`.stream()`
Copy the code
`.filter( task -> task.getStatus() == Status.OPEN )`
Copy the code
`.mapToInt( Task::getPoints )`
Copy the code
`.sum(); `Copy the code
`System.out.println( "Total points: " + totalPointsOfOpenTasks ); `Copy the code

The console output from running this method is:

Total points: 18
Copy the code

There’s a lot to be said for that. First, the Tasks collection is converted to a Steam representation; Second, the Filter operation on Steam filters out all CLOSED tasks. Third, the mapToInt operation converts the Task flow into an Integer set based on the Task::getPoints method of each task instance. Finally, the sum method is used to calculate the sum and get the final result.

There are a few things to remember about Steams before we move on to the next example. Actions on Steam can be divided into intermediate actions and late actions.

An intermediate action returns a new Steam — performing an intermediate action (such as Filter) does not perform the actual filtering, but rather creates a new Steam and puts the qualifying elements from the original steam into the newly created Steam.

Late operations, such as forEach or sum, iterate over Steam and produce results or additional results; After the late operation, the Steam processing line has been processed and is no longer usable. In almost all cases, the late action is to traverse Steam immediately.

Another value of Steam is its creative support for parallel processing. For the above set of tasks, we can calculate the sum of points for all tasks using the following code:

`// Calculate total points of all tasks`
Copy the code
`final double totalPoints = tasks`
Copy the code
`.stream()`
Copy the code
`.parallel()`
Copy the code
`.map( task -> task.getPoints() ) // or map( Task::getPoints )`
Copy the code
`.reduce( 0, Integer::sum ); `Copy the code
`System.out.println( "Total points (all tasks): " + totalPoints ); `Copy the code

Here we use the Parallel method to process all tasks in parallel and use the Reduce method to compute the final result. The console output is as follows:

Total Points (all Tasks) : 26.0Copy the code

For a set, it is often necessary to group the elements according to certain conditions. This can be done quickly using the API provided by Steam as follows:

`// Group tasks by their status`
Copy the code
`final Map< Status, List< Task > > map = tasks`
Copy the code
`.stream()`
Copy the code
`.collect( Collectors.groupingBy( Task::getStatus ) ); `Copy the code
`System.out.println( map ); `Copy the code

The console output is as follows:

{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}
Copy the code

The final example of a task set is how to calculate the number of points per task in the set as a percentage of the set, as follows:

`// Calculate the weight of each tasks (as percent of total points)`
Copy the code
`final Collection< String > result = tasks`
Copy the code
`.stream() // Stream< String >`
Copy the code
`.mapToInt( Task::getPoints ) // IntStream`
Copy the code
`.asLongStream() // LongStream`
Copy the code
`.mapToDouble( points -> points / totalPoints ) // DoubleStream`
Copy the code
`.boxed() // Stream< Double >`
Copy the code
`.mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream`
Copy the code
`.mapToObj( percentage -> percentage + "%" ) // Stream< String>`
Copy the code
`.collect( Collectors.toList() ); // List< String >`
Copy the code
`System.out.println( result ); `Copy the code

The console output is as follows:

(19%, 50%, 30%]Copy the code

Finally, as mentioned earlier, the Steam API doesn’t just work with Java collections. Traditional IO operations (reading data line by line from a file or network) can benefit from Steam processing. Here’s a quick example:

`final Path path = new File( filename ).toPath(); `Copy the code
`try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {`
Copy the code
`lines.onClose( () -> System.out.println("Done!" ) ).forEach( System.out::println ); `Copy the code
`} `Copy the code

The Stream method onClose returns an equivalent Stream with an extra handle that is executed when the Stream’s close () method is called. The Stream API, Lambda expressions, and method references supported by interface default methods and static methods are Java 8’s response to the modern paradigm of software development.

4.3 the Date/Time API (JSR 310)

Java 8 introduces new

Date/Time API(JSR 310)

To improve time and date processing. Time and date management has been one of the most painful issues for Java developers. Java.util. Date and later Java.util. Calendar never solved this problem (and made it even more confusing for developers).

For these reasons, a third-party library, Joda-Time, was created to replace Java’s Time management API. The new Time and date management API in Java 8 is heavily influenced by joda-time and incorporates much of the best of Joda-time. The new Java.time package includes all classes for date, time, time zone, Instant (date-like but accurate to nanosecond), Duration, and clock manipulation. The newly designed API takes into account the immutability of these classes (lessons learned from java.util.calendar) and returns a new object if an instance needs to be modified.

Let’s take a look at the key classes in the java.time package and their respective use examples. First, the Clock class uses the time zone to return the current nanosecond time and date. Clock can replace system.currentTimemillis () and timezone.getDefault ().

// Get the system clock as UTC offset
Copy the code
final Clock clock = Clock.systemUTC();
Copy the code
System.out.println( clock.instant() );
Copy the code
System.out.println( clock.millis() );
Copy the code

The output of this example is:

` T15:2014-04-12 wine. 282 z `Copy the code
1397315969360 ` `Copy the code

Second, look at the LocalDate and LocalTime classes. LocalDate contains only the date part of the ISO-8601 calendar system; LocalTime contains only the time portion of the calendar system. Objects for both classes can be built using the Clock object.

// Get the local date and local time
Copy the code
final LocalDate date = LocalDate.now();
Copy the code
final LocalDate dateFromClock = LocalDate.now( clock );
Copy the code
System.out.println( date );
Copy the code
System.out.println( dateFromClock );
Copy the code
// Get the local date and local time
Copy the code
final LocalTime time = LocalTime.now();
Copy the code
final LocalTime timeFromClock = LocalTime.now( clock );
Copy the code
System.out.println( time );
Copy the code
System.out.println( timeFromClock );
Copy the code

The output of the above example is as follows:

` 2014-04-12 `Copy the code
` 2014-04-12 `Copy the code
` 11:25:54. 568 `Copy the code
` 15:25:54. 568 `Copy the code

The LocalDateTime class contains information about LocalDate and LocalTime, but not the time zone information in the ISO-8601 calendar system.

// Get the local date/time
Copy the code
final LocalDateTime datetime = LocalDateTime.now();
Copy the code
final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );
Copy the code
System.out.println( datetime );
Copy the code
System.out.println( datetimeFromClock );
Copy the code

The output of this example is as follows:

` : the 2014-04-12 T11 37:52. 309 `Copy the code
` ` T15 2014-04-12:37:52. 309Copy the code

If you need data/time information for a specific time zone, you can use ZoneDateTime, which holds the date and time of the ISO-8601 date system and sometimes blocks the information. Here are some examples of using different time zones:

// Get the zoned date/time
Copy the code
final ZonedDateTime zonedDatetime = ZonedDateTime.now();
Copy the code
final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );
Copy the code
final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los\_Angeles" ) );
Copy the code
System.out.println( zonedDatetime );
Copy the code
System.out.println( zonedDatetimeFromClock );
Copy the code
System.out.println( zonedDatetimeFromZone );
Copy the code

The output of this example is:

` : the 2014-04-12 T11 47:01. 017-04:00 America/New_York `Copy the code
` T15:2014-04-12 47:01. ` 017 zCopy the code
` T08:2014-04-12 47:01. 017 - from America/Los_Angeles `Copy the code

Finally, take a look at the Duration class, which holds times down to seconds and nanoseconds. This makes it easy to calculate the difference between two dates, as shown in the following example:

`// Get duration between two dates`
Copy the code
`final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 ); `Copy the code
`final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 ); `Copy the code
`final Duration duration = Duration.between( from, to ); `Copy the code
`System.out.println( "Duration in days: " + duration.toDays() ); `Copy the code
`System.out.println( "Duration in hours: " + duration.toHours() ); `Copy the code

This example is used to calculate the number of days and hours between April 16, 2014 and April 16, 2015. The output is as follows:

Duration in days: 365
Copy the code
Duration in hours: 8783
Copy the code

The overall impression of the new Java 8 date and Time is positive, partly because of the positive impact of Joda-time and partly because officials are finally listening to the needs of developers.

4.4 Nashorn JavaScript Engine

Nashorn JavaScript engine is javax.mail. Script. Another a ScriptEngine implementation version, this kind of script engine, follow the same rules allow Java and JavaScript interaction is used, the example code is as follows:

ScriptEngineManager manager = new ScriptEngineManager();
Copy the code
ScriptEngine engine = manager.getEngineByName( "JavaScript" );
Copy the code
System.out.println( engine.getClass().getName() );
Copy the code
System.out.println( "Result:" + engine.eval( "function f() { return 1; }; f() + 1;" ));Copy the code

The output of this code is as follows:

`jdk.nashorn.api.scripting.NashornScriptEngine`
Copy the code
`Result: 2`
Copy the code

4.5 Base64

A Base64 encoding rewrite has been added to the official Java 8 library to enable Base64 encoding without the need for third-party libraries, as shown in the following example:

`package com.javacodegeeks.java8.base64; `Copy the code
`import java.nio.charset.StandardCharsets; `Copy the code
`import java.util.Base64; `Copy the code
`public class Base64s {`
Copy the code
`public static void main(String[] args) {`
Copy the code
`final String text = "Base64 finally in Java 8!" ; `Copy the code
`final String encoded = Base64`
Copy the code
`.getEncoder()`
Copy the code
`.encodeToString( text.getBytes( StandardCharsets.UTF_8 ) ); `Copy the code
`System.out.println( encoded ); `Copy the code
`final String decoded = new String(`
Copy the code
`Base64.getDecoder().decode( encoded ),`
Copy the code
`StandardCharsets.UTF_8 ); `Copy the code
`System.out.println( decoded ); `Copy the code
`} `Copy the code
`} `Copy the code

The output of this example is as follows:

`QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ==`
Copy the code
`Base64 finally in Java 8! `Copy the code

The new Base64API also supports URL and MINE encoding and decoding. (Base64.getUrlEncoder()/base64. getUrlDecoder(), base64. getMimeEncoder()/base64. getMimeDecoder())).

4.6 Parallel Arrays

The Java8 release has added many new methods to support parallel array processing. The most important method is parallelSort(), which dramatically speeds up array sorting on multicore machines. The following example demonstrates the method of the parallexXxx series:

package com.javacodegeeks.java8.parallel.arrays;
Copy the code
import java.util.Arrays;
Copy the code
import java.util.concurrent.ThreadLocalRandom;
Copy the code
public class ParallelArrays {
Copy the code
public static void main( String\[\] args ) {
Copy the code
long\[\] arrayOfLong = new long \[ 20000 \];
Copy the code
Arrays.parallelSetAll( arrayOfLong,
Copy the code
index -> ThreadLocalRandom.current().nextInt( 1000000 ) );
Copy the code
Arrays.stream( arrayOfLong ).limit( 10 ).forEach(
Copy the code
i -> System.out.print( i + " " ) );
Copy the code
System.out.println();
Copy the code
Arrays.parallelSort( arrayOfLong );
Copy the code
Arrays.stream( arrayOfLong ).limit( 10 ).forEach(
Copy the code
i -> System.out.print( i + " " ) );
Copy the code
System.out.println();
Copy the code
}
Copy the code
}
Copy the code

The code above uses the parallelSetAll() method to generate 20,000 random numbers, which are then sorted using the parallelSort() method. This program outputs the first 10 elements of an unordered and sorted array. The output of the above example code is:

`Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378`
Copy the code
`Sorted: 39 220 263 268 325 607 655 678 723 793`
Copy the code

4.7 concurrency

Based on new lambda expressions and characteristics of steam for Java 8 for Java. The util. Concurrent. ConcurrentHashMap class to add a new method to support the focus on operation; In addition, also for Java. Util. ConcurrentForkJoinPool class to add a new method to support the general thread pool operation

Java 8 also added new Java. Util. Concurrent. The locks. StampedLock class, Support based on the capacity of the lock, the lock has the support of three model is used to read and write operations, can make the lock is a Java. Util. Concurrent. The locks. The ReadWriteLock replacement).

In Java. Util. Concurrent. Atomic package also added a lot of tools, listed as follows:

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder

5. New Java tools

Java 8 provides some new command-line tools, and this section explains some of the most useful tools for developers.

5.1 Nashorn Engine: JJS

JJS is a command line tool based on the standard Nashorn engine that accepts JS source code and executes it. For example, let’s write a func.js file that looks like this:

`function f() {`
Copy the code
`return 1; `Copy the code
`}; `Copy the code
`print( f() + 1 ); `Copy the code

This command can be executed from the command line: JJS func.js, and the console output reads:

2
Copy the code

5.2 Class dependency analyzer: JDEPS

Jdeps is a great command-line tool that shows Java class dependencies at the package and class levels, takes a.class file, directory, or Jar file as input, and outputs the dependencies to the console.

To minimize the results, analyze just one JAR file: org.springFramework.core-3.0.5.release.jar.

Jdeps org. Springframework. Core - 3.0.5. The jarCopy the code

This command produces a lot of results, but let’s look at just a few of them: dependencies are grouped by package, and “Not found” is displayed if the dependency is not found on the classpath.

` org. Springframework. Core - 3.0.5. The jar - > C: \ Program Files \ Java \ jdk1.8.0 \ jre \ lib \ rt jar `Copy the code
` org. Springframework. Core (org. Springframework. Core - 3.0.5. The jar) `Copy the code
`-> java.io`
Copy the code
`-> java.lang`
Copy the code
`-> java.lang.annotation`
Copy the code
`-> java.lang.ref`
Copy the code
`-> java.lang.reflect`
Copy the code
`-> java.util`
Copy the code
`-> java.util.concurrent`
Copy the code
`-> org.apache.commons.logging not found`
Copy the code
`-> org.springframework.asm not found`
Copy the code
`-> org.springframework.asm.commons not found`
Copy the code
` org. Springframework. Core. The annotation (org. Springframework. Core - 3.0.5. The jar) `Copy the code
`-> java.lang`
Copy the code
`-> java.lang.annotation`
Copy the code
`-> java.lang.reflect`
Copy the code
`-> java.util`
Copy the code

More details are available

6. New JVM features

For JVM parameters, use -xx :MetaSpaceSize and -xx :MaxMetaspaceSize instead of -xx :PermSize and -xx :MaxPermSize.

7. Conclusion

Java 8 takes the Java platform a big step forward by providing developers with many features that increase productivity. Java 8 is not yet suitable for use in production systems, but the adoption rate is sure to increase over the next few months. Slow but improving). As a developer, it’s time to learn something about Java 8 and prepare for the upgrade.

About Spring: For enterprise-level development, we should also pay attention to the Spring community’s support for Java 8