Detailed java8 function interface, the function interface Detailed, lambda expression is an anonymous function, meaning the use of a reference method, functional interface instance, how to define the function interface

Interface function defined in detail

Function is only an abstract interface method
Because there is a default method to achieve, so they are not abstract.
If an interface defines an abstract method, but he just covers public Object methods, still do not abstract interface methods, because it will eventually get a realization somewhere. (If it is not public so count) 
That is not only an abstract method default, Object is not too public
 
Examples of functional interfaces can be referenced by a method or a lambda expression represented for reference constructor
Type must be an interface, and can not be another such class and need to comply with the requirements defined functional interface or the compiler error when using annotations
Regardless of whether they have to use notes to annotate FunctionalInterface, the compiler will satisfy any interface function interface is defined as a function of the interface that is without also OK, but obviously without it, there would be no limit constraints, follow-up may increase other methods result in an error

Common interface function

Interface java.util.function four basic package
         Interface abstract methods
  • Predicate<T>           boolean test(T t);
  • Consumer<T>          void accept(T t);
  • Function<T, R>        R apply(T t);
  • Supplier<T>             T get();
 
java.util.function.Predicate<T>
Assertion that is the condition tester reception conditions, the test
Abstract interface defines a method named test, which accepts T generic object and returns a boolean.
test (test conditions), and-or- negate (or with) Method

 

java.util.function.Consumer<T>

Consumer spending data reception parameters and returns void data is consumed
Defines an abstract method named accept that accepts the object T is generic, does not return (void)
If you need to access an object of type T, and perform certain actions, you can use this interface

 

 

java.util.function.Function<T, R>
The output function of input data conversion function
Apply a known interface defines the method, which takes a generic target T and R of the generic object returns.

 

 

java.util.function.Supplier <T>
provider is not required input, providing output data T
constructor with no arguments provided objects of type T

 

 

Why should there be a basic type extension

Only the object as a generic type parameter can, for basic types to relate to the operation of the boxing and unboxing, although automatic
But this inevitably brings to memory overhead, packing and unpacking will bring costs
Therefore, in order to reduce the performance overhead of these types of basic type extension
Some methods of the Stream class type and packing type basic distinction made
Java 8, only  integer , long integer , and double floating point do special handling because they are most frequently used in the numerical calculation
 
Way to do special treatment of the basic types are clearly defined in the name
  • If the parameter is a primitive type, not just the type name can be prefixed
  • If the method return type is a primitive type, then in a front basic type plus To
To sum it up:
Plus the type prefix [Int | Double | Long]  represents parameter is the basic type, if on this basis, has added To represent the return type is primitive 
If possible, use the basic types of special handling done as much as possible, thus improving the performance of
 

Examples of functional interface

Examples of functional interfaces can be referenced by a method or a lambda expression represented for reference constructor

Lambda expressions

Lambda expressions can be understood as a way of showing simple anonymous function may be transmitted, which is used to represent anonymous function
It has no name, but it has a list of parameters, the main function returns an exception list type, there may be a can throw.
Feature
  • Anonymous - Anonymous we say, because it is not normal methods have a clear name: write less and want much more!
  • Function - we say that it is a function, not because of Lambda function method as belonging to a particular class. But the same and methods, Lambda has a list of parameters, the main function, the return type, may also have a list of exceptions can be thrown.
  • --Lambda expression can pass as a parameter to the method, or stored in a variable.
  • Simple - no need to write as many template code like anonymous classes.
The basic syntax
 
Lambda is the basic syntax
(parameters) -> expression
Or (Note braces statement)
(parameters) -> { statements; } 
 
Lambda expressions into three parts
  1. parameter list
  2. Arrow (-> the parameter list and spaced apart from the body Lambda)
  3. Lambda body (an expression or statement)
1. The expression does not contain parameters, empty parentheses () indicate that the parameter () -> System.out.println ( "Hello World");      
2 and includes only a parameter contains parentheses may be omitted s parameters -> System.out.println ( "Hello World"); 
Body 3. Lambda expressions may be not only an expression, and may also be a block of code, curly braces ({}) to enclose block
 And the rules of the code block following the general method indistinguishable, throwing an exception may be used to exit or return.
 Only one line of code Lambda expressions can also be used braces to clear Lambda expressions where to start, where to end.
() -> {
    System.out.print("Hello");
    System.out.println(" World");
};
4. Lambda expressions can also represent a method comprising a plurality of parameters (Long x, Long y) -> x + y; 
5. 4 expression can be simplified, (x, y) -> x + y; which we will discuss below by means of type inference 
 
 
Lambda only reference values ​​instead of variables (in fact requires final)
When an anonymous inner classes, methods need to refer to it in the variable, the variable needs to be declared as final 
Lambda expressions are not required to be final but variable, the variable must be a fait accompli in the final 
The final is in fact only refers to the variable assignment once. In other words, Lambda expressions quoted are values ​​instead of anonymous inner classes with similar variables, using a copy of the variable value so it is necessary not to change
If you try to assign the variable times, and then reference it in Lambda expressions, the compiler will error
such as:
image_5b791352_6367
Everything is running normally no need to set final
image_5b791352_2916
Once a hello variable value reassignments, the compiler will report an error
image_5b791352_49aa
 
 
 

Method references

Method references so that you can reuse the existing definition method and pass them as the same Lambda
The method of use :: to indicate references
There are three main methods references
(1) points to the static method reference method (such as Integer parseInt method of writing Integer :: parseInt) 
      That is, static methods acting on the object
 
image_5b791352_7e3a
Example: value character string into
image_5b791352_549f
image_5b791352_66ad
 
 
 
(2) points to any type of method reference example of a method (e.g., the length String method, String :: writing length)
  In the process you refer to an object, and the object itself is a parameter of Lambda. For example, Lambda expressions (String s) -> s.toUppeCase () can be written as String :: toUpperCase  
 
image_5b791352_6794
 
Example: the length of the print string 1 3 2 (without spaces and line breaks so squeezed together)
image_5b791352_4119
image_5b791352_5b8a
 
 
(3) Examples of the method object reference points to an existing
For example charAt lambda expression string helloString call () method is an existing object helloString
image_5b791352_242a
Examples: Get charAt string at a given value of the sequence
image_5b791352_1b9c
image_5b791352_35bf
 

Constructor references

For an existing constructor, you can make use of its name and the new keyword to create a reference to it:
ClassName::new
It functions as a reference point to the static method similar
 
定义Class A   三个属性 设置了默认值 以观察构造方法的调用情况
Copy the code
class A {
private String s1="a";
private String s2="b";
private String s3="c";
A(){
}
A(String s1){
this.s1=s1;
}

A(String s1,String s2){
this.s1=s1;
this.s2=s2;
}
A(String s1,String s2,String s3){
this.s1=s1;
this.s2=s2;
this.s3=s3;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("A{");
sb.append("s1='").append(s1).append('\'');
sb.append(", s2='").append(s2).append('\'');
sb.append(", s3='").append(s3).append('\'');
sb.append('}');
return sb.toString();
}
}
Copy the code

 

image_5b791352_489c
image_5b791352_425
可以看到分别调用了,无参构造方法 一个参数构造方法以及两个参数构造方法
 
如果三个构造方法如何设置呢?
我们只需要定义函数接口即可
image_5b791352_6d59
 
image_5b791352_35c0
再次运行
image_5b791352_a33
 
 
 
 

类型检查与类型推断

 

类型检查

我们知道当我们操作赋值运算时会有类型检查
比如:
image_5b791352_16d2
那么对于函数式接口与函数值呢 
函数式接口 变量名 = Lambda-匿名函数/方法引用/构造方法引用;
 
那么函数作为值是如何进行类型检查的?
 
Lambda的类型是从使用Lambda的上下文推断出来的
上下文中Lambda表达式需要的类型称为目标类型
上下文是比如接受它传递的方法的形式参数,或接受它的值的局部变量
形式参数或者局部变量都会有类型的定义与声明
 
比如筛选 1~9之中小于5的数值

List<Integer> listNum = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

List filteredNum = listNum.stream().filter(i -> i.compareTo(5) <0).collect(Collectors.toList());

System.out.println(filteredNum);

image_5b791352_5a3e
这个示例中接收  Lambda表达式  作为参数的形式参数为  Predicate<? super T> predicate
也就是目标类型    函数接口为Predicate<T> 
找到了目标类型 我们的T为Integer
也就是Predicate<Integer> 
他的抽象方法为 boolean test(T t);   也就是  boolean test(Integer t);  接收一个Integer返回一个boolean
我们的Lambda匿名函数 i -> i.compareTo(5) < 0 就是接收一个Integer  返回一个boolean 所以类型检查通过
简单说就是:
1. 通过形参类型或者变量类型 找到函数接口进而找到抽象方法的声明
2. 然后在与参数值进行比对查看是否匹配
 
可以看得出来,Lambda表达式最终匹配的是 函数接口中的抽象方法的方法签名
如果不同的函数接口,具有相互兼容的抽象方法签名  那么一个Lambda表达式显然可以匹配多个函数接口
 
特殊的void兼容规则
如果一个Lambda的主体是一个语句表达式, 它就和一个返回void的函数描述符兼容(当然需要参数列表也兼容)。
就是说 如果主体是一个语句,不管做什么或者调用方法返回其他的类型,他都可以兼容void
 
例如
List的add方法   boolean add(E e);

List<String> list= new ArrayList<>();

// Predicate返回了一个boolean

Predicate<String> p = s -> list.add(s);

// Consumer返回了一个void

Consumer<String> b = s -> list.add(s);

上面的代码都可以通过编译,并且运行
 

类型推断

 
类型推断的概念,在Java中不是第一次出现
Java SE 7之前,声明泛型对象的代码如下
List<String> list = new ArrayList<String>();
Java 7中,可以使用如下代码:
List<String> list = new ArrayList<>();
这就是类型推断  ,一个最直接直观的好处就是可以简化代码的书写,这不就是语法糖么
 
针对 Lambda表达式也有类型推断
Java编译器可以根据  上下文(目标类型)推断出用什么函数式接口来配合Lambda表达式
然后就可以获取到函数接口对应的函数描述符也就是那个抽象方法的方法签名
编译器可以了解Lambda表达式的参数类型,这样就可以在Lambda语法中省去标注参数类型
 
 
比如刚才的筛选 1~9之中小于5的数值的例子中,就可以有如下几种写法

.filter((Integer i) -> { return i.compareTo(5) < 0;}).collect(Collectors.toList());

.filter((Integer i) ->i.compareTo(5) < 0).collect(Collectors.toList());

.filter(i ->i.compareTo(5) < 0).collect(Collectors.toList());

 
 

如何使用函数式接口

 
函数式接口定义了函数的类型   有了类型就如同其他类型 比如 int 一样  
你可以定义变量
你可以传递参数
你可以返回
 
一个函数方法有方法签名和方法体两部分内容组成
函数接口只是有了方法签名
Examples of the method body transfer interface function (i.e. Lambda expressions - the anonymous constructor function method cited references)
Specific call is abstract method called abstract method is an example of the method body functional interface
such as:
Defines a function interface may be used such as pre like Predicate
image_5b791352_7e92
 
Lambda then is the definition of the variables used to instantiate
Then followed by a method call
image_5b791352_67c
image_5b791352_dfa
 
 

Transfer: https://www.cnblogs.com/noteless/p/9501253.html#

Guess you like

Origin www.cnblogs.com/heqiyoujing/p/11450547.html