Function-Type interface
A core concept introduced in Java 8 is the functional interface (functional Interfaces). By adding an abstract method to the interface, these methods can be run directly from the interface. If an interface defines a unique abstract method, then this interface becomes a functional interface. At the same time, a new annotation was introduced: @FunctionalInterface. Can put him in front of an interface, indicating that this interface is a functional interface. This annotation is not necessary, as long as the interface contains only one method interface, the virtual opportunity is automatically judged, but it is best to use annotations @FunctionalInterface on the interface to declare. A @FunctionalInterface interface is added to the interface, only one abstract method is allowed, or the compiler will error.
Java.lang.Runnable is a function-type interface.
@FunctionalInterfacepublic interface Runnable {public abstract void run ();
Lambda expression
The important properties of the functional interface are that we can instantiate them using lambda, which allows you to use the function as a method parameter or treat the code as data. The introduction of lambda expressions gives developers a number of advantages: Before Java 8, the use of anonymous internal classes, listeners and event handlers is lengthy, code readability is poor, and lambda expression applications make the code more compact and readable; lambda The expression makes the large collection of parallel operations very convenient, can give full play to the advantages of multi-core CPU, more easy to write code for multi-core processor;
A LAMBDA expression consists of three parts: the first part is a comma-delimited form parameter in parentheses, and the parameter is the parameter of the method inside the function interface; The second part is an arrow symbol:->; the third part is the method body, which can be an expression and a code block. The syntax is as follows:
1. The method body is an expression, and the value of the expression is returned as a return value.
(parameters), expression
2. The method body is a code block, must be wrapped with {}, and need a return value, but if the function interface inside the method return value is void, there is no need to return a value.
(parameters), {statements;} For example, the following is a code comparison using anonymous inner classes and LAMBDA expressions.
Here's the code for the anonymous inner class:
Button.addactionlistener (new ActionListener () {@Overridepublic void actionperformed (ActionEvent e) {System.out.print ("Helllo Lambda in Actionperformed");}); Following is the use of a LAMBDA expression: Button.addactionlistener (\\actionPerformed has a parameter e passed in, so use (ActionEvent e) (ActionEvent e)- System.out.print ("Helllo Lambda in Actionperformed"));
Above is the method body containing the parameter passed in (ActionEvent e), if there is no argument then just (), for example, the Run method in Thread has no parameters passed in, when it uses a LAMBDA expression:
Thread t = new Thread (\\run no arguments passed in, so use (), followed by {} Wrap Method Body (), {System.out.println ("Hello from a thread in Run");}); By comparing the above two codes, you can see that using LAMBDA expressions simplifies your code and makes your code more readable. To further simplify the LAMBDA expression, you can use a method reference. For example, the following three comparisons are using inner classes, using LAMBDA representations and using method references://1. Using the inner class Function<integer, string> f = new function<integer,string> () {@Overridepublic String apply (Integer t) { Return null;}};/ /2. Use LAMBDA expression Function<integer, string> F2 = (t)->string.valueof (t); 3. How to use the method reference Function<integer, string> f1 = string::valueof;
To use lambda expressions, you need to define a functional interface, which tends to flood your program with an overdose of functional interfaces that are only LAMBDA expression services. To reduce such an excess of functional interfaces, Java 8 adds a number of new functional generic interfaces to java.util.function. For example:
Function<t, R>: T as input, return R as output, and he also contains the default methods for combining other functions.
Predicate<t>: Takes T as input and returns a Boolean value as the output that contains several default methods to synthesize the predicate group into other complex logic (and, or, non).
Consumer<t>: Takes T as input, does not return anything, and represents an operation on a single parameter.
For example, there is a method in the,people class getMaleList need to get a list of males, here you need to define a functional interface PersonInterface:interface Personinterface { public boolean test (Person person);} public class people { private list<person> persons= new Arraylist<person> (); public list<person> getmalelist (PersonInterface filter) { List<Person> res = new ArrayList<Person> ( persons.foreach); (Person person) -> { if (filter.test (person)) {//call personinterface method res.add (person); } } ); return res; }} In order to remove personinterface This functional interface, you can use the General function interface Predicate Replace the following:class people{ private list< Person> persons= new arraylist<person> (); public list<person> Getmalelist (predicate<person> predicate) { list&Lt Person> res = new arraylist<person> (); persons.foreach ( person - > { if (Predicate.test (person)) {//Call Predicate abstract method test res.add ( person); } }); return res; }}
Enhancements to interfaces
Java 8 has made further enhancements to the interface. You can add non-abstract methods that use the default keyword adornment in an interface. You can also define static methods in the interface. Today, interfaces look more and more like the functions of abstract classes.
Default method
Java 8 also allows us to add a non-abstract method implementation to the interface, just using the default keyword, which is also called the extension method. When the interface is implemented, the default extension method can be used directly on subclasses, which are used in a manner similar to non-abstract member methods in abstract classes. However, the extension method is not able to overload the method in Object. For example: toString, equals, hashcode cannot be overloaded in the interface.
For example, a default method count () is defined in the following interface, which can be used directly in subclasses.
Public interface Defaultfuninterface {//define default method Countdefault int count () {return 1;}} public class Subdefaultfunclass implements Defaultfuninterface {public static void main (string[] args) {//Instantiate a subclass object, The subclass object can be called directly from the default method in the parent interface, count Subdefaultfunclass sub = new Subdefaultfunclass (); Sub.count ();}}
Static methods
In the interface, it is also possible to define a static method. The static method in the interface can be invoked directly with the interface.
For example, the following interface defines a static method, find, which can be called directly with Staticfuninterface. Find ().
Public interface Staticfuninterface {public static int find () {return 1;}} public class Teststaticfun {public static void main (string[] args) {//The static method defined in the interface find is called directly staticfuninterface.fine ();}}
Collection-Flow operation
Java 8 introduces a streaming operation that enables parallel processing and functional manipulation of collections (Collection). Depending on the results returned by the operation, the flow operation is divided into intermediate operation and final operation. The final operation returns a specific type of result, and the intermediate operation returns the stream itself so that multiple operations can be concatenated in sequence. Depending on the concurrency of the stream, the stream can be divided into two types: serial and parallel. Streaming operation realizes the filtering, sorting, mapping and other functions of the collection.
The difference between the stream and the Collection collection: Collection is a static memory data structure, and the stream is calculated. The former is mainly memory-oriented, stored in memory, the latter is mainly CPU-oriented, CPU-based implementation of the calculation.
Serial and parallel streams
The stream has both serial and parallel, and the operation on the serial stream is done sequentially in one thread, while the parallel stream is executed concurrently on multiple threads. Parallel and serial streams can switch from one another: a serial stream is returned through Stream.sequential (), and a parallel stream is returned through Stream.parallel (). Compared with the serial stream, the parallel flow can greatly improve the execution efficiency of the program.
The following is a sequential and parallel way to sort the collection.
Serial sequencing:
list<string> list = new arraylist<string> (); for (int i=0;i<1000000;i++) {Double d = math.random () *1000; List.add (d+ "");} Long start = System.nanotime ();//Gets the point in time that the system starts sorting int count= (int) (Stream) List.stream (). Sequential ()). Sorted (). Count (); Long end = System.nanotime ();//Get the system to end sort the point in time long ms = TimeUnit.NANOSECONDS.toMillis (End-start);// The time System.out.println (ms+ "MS") used to get the serial sort;
Parallel sorting:
list<string> list = new arraylist<string> (); for (int i=0;i<1000000;i++) {Double d = math.random () *1000; List.add (d+ "");} Long start = System.nanotime ();//Gets the time point at which the system begins sorting int count = (int) (Stream) List.stream (). Parallel ()). Sorted (). Count (); Long end = System.nanotime ();//Get the system to end sort the point in time long ms = TimeUnit.NANOSECONDS.toMillis (End-start);// The time System.out.println (ms+ "MS") used in parallel sequencing is obtained, the serial output is 1200ms and the parallel output is 800ms. It can be seen that parallel sorting time is much less than the serial sort time.
Intermediate operation
This operation keeps the stream in an intermediate state, allowing for further action. It returns the Stream, which allows for more chained operations. The Common intermediate operations are:
Filter (): Filters the elements;
Sorted (): sort the elements;
Map (): Mapping of elements;
Distinct (): Remove duplicate elements;
Substream (): Gets the child Stream, and so on.
For example, the following is a collection of strings that is filtered, returns a collection of strings beginning with "s", and prints the collection sequentially:
List.stream (). Filter ((s), S.startswith ("s")). ForEach (System.out::p rintln);
The filter (...) Here is an intermediate operation that can be chained to other Stream operations.
Terminate operation
The operation must be the last action of the stream, and once called, the stream is in a signaled state and can no longer be used. The common termination actions are:
ForEach (): handles each element;
ToArray (): Exports the element to an array;
FindFirst (): Returns the first matching element;
AnyMatch (): whether there are matching elements and so on.
For example, the following is a collection of strings that is filtered, returns a collection of strings beginning with "s", and prints the collection sequentially:
List.stream ()//Gets the stream operand of the list. Filter ((s), S.startswith ("s"))//filter operation on this stream. ForEach (system.out::p rintln);
The ForEach (...) here is a terminate operation that cannot be chained again after the operation has been added.
Update for annotations
For annotations, Java 8 mainly has two improvements: type annotations and repeating annotations.
The type annotations for Java 8 extend the scope used by annotations. Before this version, annotations can only be used where they are declared. Now you can add annotations to almost anything: local variables, classes, and interfaces, and even exceptions to methods can be added. Added two annotated program element types Elementtype.type_use and Elementtype.type_parameter are used to describe the new occasion for annotations. Elementtype.type_parameter indicates that the note can be written in a declaration statement of a type variable. Instead, Elementtype.type_use indicates that the note can be written in any statement that uses a type, such as a type in a declaration statement, a generic, and a cast statement.
Support for type annotations enhances the ability to discover errors through static analysis tools. Problems that could have been found only at run time can be detected in advance at compile time. Java 8 itself does not have a framework for its own type detection, but it can automatically check and confirm software defects and improve productivity by using third-party tools such as the Checker framework.
For example, the following code can be compiled, but the runtime will report an NullPointerException exception.
public class Testanno {public static void main (string[] args) {Object obj = null;obj.tostring ();}}
In order to automatically check for such exceptions during compilation, you can use the type annotations in conjunction with the Checker Framework to troubleshoot early:
Import Org.checkerframework.checker.nullness.qual.nonnull;public class Testanno {public static void main (string[] args {@NonNull Object obj = null;obj.tostring ();}}
The automatic test results at compile time are as follows:
C:\workspace\testjava8\src\testanno.java:4: Warning: (assignment.type.incompatible) $$ 2 $$ null $$ @ Unknowninitialization @NonNull Object $$ (156) $$ incompatible types in assignment. @NonNull object obj = null; ^ Found:null Required: @UnknownInitialization @NonNull Object
In addition, one limitation of using annotations before this version is that the same annotations can only be declared once at the same location and cannot be declared more than once. Java 8 introduces a repeating annotation mechanism so that the same annotations can be declared multiple times in the same place. The repeating annotation mechanism itself must be annotated with @Repeatable.
For example, here is an example of repeating annotations with @Repeatable:
@Retention (retentionpolicy.runtime) \ \ The annotation exists in the class file and can be obtained @interface annots {annot[] value () at run time by reflection, @Retention ( Retentionpolicy.runtime) \ \ The annotation exists in the class file and can be obtained by reflection at run time @repeatable (annots.class) @interface Annot {String value ();} @Annot ("A1") @Annot ("A2") public class Test {public static void main (string[] args) {Annots annots1 = Test.class.getAnnotat Ion (Annots.class); System.out.println (Annots1.value () [0]+ "," +annots1.value () [1]); Output: @Annot (VALUE=A1), @Annot (VALUE=A2) annot[] annots2 = Test.class.getAnnotationsByType (Annot.class); System.out.println (annots2[0]+ "," +annots2[1]); Output: @Annot (VALUE=A1), @Annot (VALUE=A2)}}
Note Annot is annotated with the @Repeatable (Annots.class). Annots is just a container that contains a Annot array, and the compiler tries to hide its presence from the programmer. In this way, the Test class can be annotated two times by Annot. The type of the repeating comment can be returned by using the Getannotationsbytype () method.
Security
Today, there are various potential threats in the Internet environment, and security is particularly important for the Java platform. To ensure a higher level of security for the new version, Java 8 has increased security in many ways and has postponed its release date. Here are some examples of security updates:
Support for stronger password-based encryption algorithms. AES-based cryptographic algorithms, such as pbewithsha256andaes_128 and pbewithsha512andaes_256, have been added.
On the client side, TLS1.1 and TLS1.2 are set to the default boot. It can also be configured with the new system property bag Jdk.tls.client.protocols.
Keystore enhancements, including the new Keystore type Java.security.DomainLoadStoreParameter and for Keytool This security key and certificate management tool adds a new command-line option,-importpassword. At the same time, some security-related APIs have been added and updated to support KeyStore updates.
A secure random number generator is supported. If the random number comes from a seed that is not random, then those systems that use random numbers to generate keys or hash sensitive information are more vulnerable. The Getinstancestrong method of the SecureRandom class now obtains the strongest random number object instance for each platform, which generates random numbers with higher entropy, such as RSA private keys and public keys.
The JSSE (Java (TM) Secure Socket Extension) server side begins to support the SSL/TLS server name recognition SNI (server name Indication) extension. The SNI extension purpose is that the SSL/TLS protocol can be extended by SNI to identify the server name that the client is attempting to connect through the handshake protocol. In Java 7, the SNI extension is only started by default on the client. Today, the SNI extension is also beginning to be supported on the JSSE server side.
The encryption method with poor security is disabled by default. The DES-related Kerberos 5 encryption method is not supported by default. If you must use this kind of weak encryption method, you need to add Allow_weak_crypto=true in the krb5.conf file. Given that this type of encryption is extremely secure, developers should try to avoid using it.
The improvement of Io/nio
Java 8 also made some improvements to Io/nio. The main include: improved Java.nio.charset.Charset implementation, so that the efficiency of encoding and decoding is improved, but also to streamline the Jre/lib/charsets.jar package, optimized String (byte[],*) construction method and The performance of the String.getbytes () method also adds some new Io/nio methods that can be used to get the stream from a file or input stream (Java.util.stream.Stream), which simplifies the processing of text lines, directory traversal, and File lookup.
The new APIs are as follows:
Bufferedreader.line (): Returns the flow of a text line stream<string>
File.lines (Path, Charset): Returns the stream of the text line stream<string>
File.list (Path): Traverse files and directories in the current directory
File.walk (Path, int, filevisitoption): Iterates through all files and subdirectories of a specified depth in a directory
File.find (Path, int, bipredicate, filevisitoption ...): Find the appropriate file
The following is a streaming operation that lists all the files and directories in the current directory:
Files.list (New File ("."). Topath ()). ForEach (System.out::p rintln);
Global capabilities
The Java 8 release also provides a complete globalization feature: Support for the new Unicode 6.2.0 standard, a new calendar and localized API, improved date-time management, and more.
Java has a long history of date and time APIs, and the time, date, and other time-date formatting classes in previous versions of Java 8 have been criticized for their high-thread-safety, heavyweight, and serialization-cost issues. Java 8 absorbs the essence of joda-time and creates an excellent API for Java in a new beginning. The new java.time contains all about clocks, local dates (localdate), local time (localtime), Local date time (LocalDateTime), Time zone (zoneddatetime) and Duration (Duration) classes. The historic date class adds the Toinstant () method for converting Date to a new representation. These new localization time-of-day APIs greatly simplify time-of-day and localized management.
For example, here's a simple application for localdate,localtime:
Localdatelocaldate localdate = Localdate.now (); Get local Date Localdate = Localdate.ofyearday (2014, 200); Get the NO. 200 day of 2014 System.out.println (localdate.tostring ());//output: 2014-07-19localdate = Localdate.of (2014, Month.september, 10); September 10, 2014 System.out.println (localdate.tostring ());//output: 2014-09-10//localtimelocaltime localtime = Localtime.now (); Gets the current time System.out.println (Localtime.tostring ());//output current time LocalTime = Localtime.of (10, 20, 50);//Get 10:20:50 The point in Time System.out.println (Localtime.tostring ());//output: 10:20:50//clock clock clocks = Clock.systemdefaultzone ();// Gets the system default time zone (current instantaneous time) long Millis = Clock.millis ();//
Java 8 Development environment
With the release of Java 8, many Ides are also beginning to provide support for Java 8. Eclipse is the most common integrated development environment for Java developers and has added support for Java 8 by default in the latest Eclipse Kepler 4.3.2 release. To add support for Java 8 in previous versions of Eclipse Kepler, you can do this in the following steps:
1. Select "Help > Eclipse Marketplace ...".
2. Enter "Java 8 Kepler" in the search box.
3. Click Install Java 8 for Eclipse Kepler SR2.
Figure 1. Installing Java 8 support for Eclipse Kepler SR2
Next, you can start the Java 8 programming journey.
Figure 2. The Java 8 program and running results that Eclipse writes:
Conclusion
The Java 8 release is a significantly changed version that has made significant improvements to Java. This paper introduces the main new features in the new version through text description and code example: function interface, LAMBDA expression, set flow operation, annotation, security, Io/nio, globalization function. In addition to the important new features described in this article, Java 8 also has many improvements and enhancements to the Java Toolkit JDBC, Java DB, JavaFX, and more. These new features simplify development, improve code readability, enhance code security, improve code execution efficiency, and create a new Java development experience for developers, driving the platform for Java to move forward.
Overview of new features in Java 8