Ao usar expressões lambda, o código que realmente passamos é uma solução: o que fazer com quais parâmetros. Imagine que existe tal situação: o esquema de operação que especificamos no Lambda já possui o mesmo esquema, então é necessário reescrever a lógica?
Claro que você não precisa. Neste momento, o que vamos explicar hoje é usado: o caractere de referência do método Java "::".
// Lambda 表达式写法:
s -> System.out.println(s);
// :: 方法引用写法:
System.out::println
Podemos usar o esquema existente por meio de referências de métodos para tornar as expressões mais concisas.
texto
Em Java 8, os dois pontos :: são chamados de "operador de referência de método", o símbolo :: é um operador de referência, e a expressão na qual ele está localizado é chamada de referência de método, e podemos usá-lo para fazer referência a um método de uma classe.
:: refere-se a um método de uma classe e retorna uma interface de função ( function interface ), que é equivalente a uma expressão lambda, mas diferente de uma expressão lambda, uma expressão lambda precisa personalizar um corpo lambda, enquanto :: se refere a um método.
/**
* 表示接受一个参数并生成结果的函数。
* @param<T>函数的输入类型
* @param<R>函数结果的类型
* @从1.8开始
*/
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
Existem quatro tipos de operadores de referência de método:
- ClassName :: New : uma referência ao construtor, equivalente a criar um objeto;
- ClassName :: static_method : Se houver parâmetros, os parâmetros serão usados como os parâmetros reais do método;
- ClassName :: instance_method : O primeiro parâmetro é usado como um objeto de classe para chamar instance_method, e outros parâmetros são usados como parâmetros de método;
- instance :: instance_method : Se houver parâmetros, os parâmetros serão usados como os parâmetros reais do método;
caso
Abaixo, uma breve demonstração do uso dos quatro tipos de referências Java:
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Supplier;
/** 引用操作符的四种类型 */
public class JavaTest {
public static class User {
private String id;
private Integer age;
private String name;
// ... 省略了参数的get(),set()方法
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("id='").append(id).append('\'');
sb.append(", age=").append(age);
sb.append(", name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
public static void testStatic(String s){
System.out.println(s);
}
}
/**
* 1.构造器引用
* ClassName::New => new ClassName()
* 如果调用时有参数,相当于调用带参的构造函数
*/
@Test
public void test1(){
App.toString(User::new);
}
public static void toString(Supplier supplier){
System.out.println(supplier.get().toString());
}
/**
* 2.静态方法引用
* ClassName::static_method =》 CLassName.static_method()
* 如果调用时有参数,直接放到静态方法的形参中
*/
@Test
public void test2(){
Arrays.asList("name1","name2").stream().forEach(User::testStatic);
}
/**
* 3.特定类对方法引用
* ClassName::instance_method => obj.instance_method(xxx)
* 调用时参数:第一个参数是实体对象 上面的obj
* 如果有其他参数,会传到方法中
*/
@Test
public void test3(){
User user = new User();
user.setId("625");
user.setAge(30);
user.setName("java punk");
Optional.of(user).ifPresent(User::toString);
}
/**
* 4.特定对象对方法引用
* instance::instance_method =》instance.instance_method(xxxx);
* 如果有参数,参数就是方法的参数
*/
@Test
public void test4(){
User user = new User();
user.setId("625");
user.setAge(30);
user.setName("java punk");
toString(user::toString);
}
}